From 2c57fe9826ddc915663489787bdd09499e05ff2b Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 2 Jul 2024 10:26:15 +0100 Subject: [PATCH] cmd/mountlib: convert time.Duration option to fs.Duration --- cmd/mount/dir.go | 4 ++-- cmd/mount/file.go | 2 +- cmd/mount/mount.go | 3 ++- cmd/mount2/fs.go | 7 ++++--- cmd/mount2/mount.go | 5 +++-- cmd/mountlib/mount.go | 28 ++++++++++++++-------------- cmd/serve/docker/options.go | 4 ++-- fs/rc/params.go | 6 ++++++ 8 files changed, 34 insertions(+), 25 deletions(-) diff --git a/cmd/mount/dir.go b/cmd/mount/dir.go index c044fcff3..7cf1c75e6 100644 --- a/cmd/mount/dir.go +++ b/cmd/mount/dir.go @@ -30,7 +30,7 @@ var _ fusefs.Node = (*Dir)(nil) // Attr updates the attributes of a directory func (d *Dir) Attr(ctx context.Context, a *fuse.Attr) (err error) { 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.Uid = d.VFS().Opt.UID 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 { 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 // We must return the same fuse nodes for vfs Nodes node, ok := mnode.Sys().(fusefs.Node) diff --git a/cmd/mount/file.go b/cmd/mount/file.go index da0897fb8..6e7b67355 100644 --- a/cmd/mount/file.go +++ b/cmd/mount/file.go @@ -25,7 +25,7 @@ var _ fusefs.Node = (*File)(nil) // Attr fills out the attributes for the file func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) { 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() Size := uint64(f.File.Size()) Blocks := (Size + 511) / 512 diff --git a/cmd/mount/mount.go b/cmd/mount/mount.go index 4fa832b57..0cc9ae651 100644 --- a/cmd/mount/mount.go +++ b/cmd/mount/mount.go @@ -6,6 +6,7 @@ package mount import ( "fmt" "runtime" + "time" "bazil.org/fuse" 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()) } 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 { fs.Errorf(nil, "-o/--option not supported with this FUSE backend") diff --git a/cmd/mount2/fs.go b/cmd/mount2/fs.go index 8ede62af1..4aa9afcd0 100644 --- a/cmd/mount2/fs.go +++ b/cmd/mount2/fs.go @@ -7,6 +7,7 @@ package mount2 import ( "os" "syscall" + "time" "github.com/hanwen/go-fuse/v2/fuse" "github.com/rclone/rclone/cmd/mountlib" @@ -88,14 +89,14 @@ func setAttr(node vfs.Node, attr *fuse.Attr) { // fill in AttrOut from node func (f *FS) setAttrOut(node vfs.Node, out *fuse.AttrOut) { setAttr(node, &out.Attr) - out.SetTimeout(f.opt.AttrTimeout) + out.SetTimeout(time.Duration(f.opt.AttrTimeout)) } // fill in EntryOut from node func (f *FS) setEntryOut(node vfs.Node, out *fuse.EntryOut) { setAttr(node, &out.Attr) - out.SetEntryTimeout(f.opt.AttrTimeout) - out.SetAttrTimeout(f.opt.AttrTimeout) + out.SetEntryTimeout(time.Duration(f.opt.AttrTimeout)) + out.SetAttrTimeout(time.Duration(f.opt.AttrTimeout)) } // Translate errors from mountlib into Syscall error numbers diff --git a/cmd/mount2/mount.go b/cmd/mount2/mount.go index 7eee41057..4548705a5 100644 --- a/cmd/mount2/mount.go +++ b/cmd/mount2/mount.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "runtime" + "time" fusefs "github.com/hanwen/go-fuse/v2/fs" "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 opts := fusefs.Options{ MountOptions: *mountOpts, - EntryTimeout: &opt.AttrTimeout, - AttrTimeout: &opt.AttrTimeout, + EntryTimeout: (*time.Duration)(&opt.AttrTimeout), + AttrTimeout: (*time.Duration)(&opt.AttrTimeout), GID: VFS.Opt.GID, UID: VFS.Opt.UID, } diff --git a/cmd/mountlib/mount.go b/cmd/mountlib/mount.go index c8c0ac6fb..5fdf991ac 100644 --- a/cmd/mountlib/mount.go +++ b/cmd/mountlib/mount.go @@ -45,16 +45,16 @@ type Options struct { DefaultPermissions bool WritebackCache 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 ExtraOptions []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 VolumeName string NoAppleDouble bool NoAppleXattr bool - DaemonTimeout time.Duration // OSXFUSE only + DaemonTimeout fs.Duration // OSXFUSE only AsyncRead bool NetworkMode bool // Windows only DirectIO bool // use Direct IO for file access @@ -64,10 +64,10 @@ type Options struct { // DefaultOpt is the default values for creating the mount var DefaultOpt = Options{ MaxReadAhead: 128 * 1024, - AttrTimeout: 1 * time.Second, // how long the kernel caches attribute for - NoAppleDouble: true, // use noappledouble by default - NoAppleXattr: false, // do not use noapplexattr by default - AsyncRead: true, // do async reads by default + AttrTimeout: fs.Duration(1 * time.Second), // how long the kernel caches attribute for + NoAppleDouble: true, // use noappledouble by default + NoAppleXattr: false, // do not use noapplexattr by default + AsyncRead: true, // do async reads by default } type ( @@ -111,18 +111,18 @@ func init() { case "darwin": // DaemonTimeout defaults to non-zero for macOS // (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 { case "linux": // Linux provides /proc/mounts to check mount status // 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": // On BSD we can't check mount status yet // 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 @@ -136,12 +136,12 @@ var Opt Options func AddFlags(flagSet *pflag.FlagSet) { rc.AddOption("mount", &Opt) 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.ExtraFlags, "fuse-flag", "", []string{}, "Flags or arguments to be passed direct to libfuse/WinFsp (repeat if required)", "Mount") // 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.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.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") @@ -160,7 +160,7 @@ func AddFlags(flagSet *pflag.FlagSet) { // 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") // 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 ( @@ -258,7 +258,7 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm handle := atexit.Register(func() { killDaemon("Got interrupt") }) - err = WaitMountReady(mnt.MountPoint, Opt.DaemonWait, mountDaemon) + err = WaitMountReady(mnt.MountPoint, time.Duration(Opt.DaemonWait), mountDaemon) if err != nil { killDaemon("Daemon timed out") } diff --git a/cmd/serve/docker/options.go b/cmd/serve/docker/options.go index c62327eaf..77ac82b30 100644 --- a/cmd/serve/docker/options.go +++ b/cmd/serve/docker/options.go @@ -185,7 +185,7 @@ func getMountOption(mntOpt *mountlib.Options, opt rc.Params, key string) (ok boo case "debug-fuse": mntOpt.DebugFUSE, err = opt.GetBool(key) case "attr-timeout": - mntOpt.AttrTimeout, err = opt.GetDuration(key) + mntOpt.AttrTimeout, err = opt.GetFsDuration(key) case "option": mntOpt.ExtraOptions, err = getStringArray(opt, key) case "fuse-flag": @@ -193,7 +193,7 @@ func getMountOption(mntOpt *mountlib.Options, opt rc.Params, key string) (ok boo case "daemon": mntOpt.Daemon, err = opt.GetBool(key) case "daemon-timeout": - mntOpt.DaemonTimeout, err = opt.GetDuration(key) + mntOpt.DaemonTimeout, err = opt.GetFsDuration(key) case "default-permissions": mntOpt.DefaultPermissions, err = opt.GetBool(key) case "allow-non-empty": diff --git a/fs/rc/params.go b/fs/rc/params.go index b6d5545f1..392fa9f13 100644 --- a/fs/rc/params.go +++ b/fs/rc/params.go @@ -283,6 +283,12 @@ func (p Params) GetDuration(key string) (time.Duration, error) { 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 // rc.Param from a path, input Params, error and a suggested HTTP // response code.