From 393b94bb70041225202d469e406cddf83b4fe62f Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 4 Feb 2020 10:56:00 +0000 Subject: [PATCH] vfs: add --vfs-read-wait and --vfs-write-wait flags --vfs-read-wait duration Time to wait for in-sequence read before seeking. (default 5ms) --vfs-write-wait duration Time to wait for in-sequence write before giving error. (default 1s) See: https://forum.rclone.org/t/constantly-high-iowait-add-log/14156 --- vfs/read.go | 7 ++++--- vfs/vfs.go | 4 ++++ vfs/vfsflags/vfsflags.go | 2 ++ vfs/write.go | 3 ++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/vfs/read.go b/vfs/read.go index 880314e5a..526467616 100644 --- a/vfs/read.go +++ b/vfs/read.go @@ -232,9 +232,10 @@ func (fh *ReadFileHandle) readAt(p []byte, off int64) (n int, err error) { if gap := off - fh.offset; gap > 0 && gap < int64(8*maxBuf) { // Set a background timer so we don't wait for long // Waits here potentially affect all seeks so need to keep them short - // This time here was made by finding the smallest when mounting a local backend - // that didn't cause seeks. - const maxWait = 5 * time.Millisecond + // The default time here was made by finding the + // smallest when mounting a local backend that didn't + // cause seeks. + maxWait := fh.file.d.vfs.Opt.ReadWait timeout := time.NewTimer(maxWait) done := make(chan struct{}) abort := int32(0) diff --git a/vfs/vfs.go b/vfs/vfs.go index 1bab8810a..58e7630b1 100644 --- a/vfs/vfs.go +++ b/vfs/vfs.go @@ -53,6 +53,8 @@ var DefaultOpt = Options{ ChunkSizeLimit: -1, CacheMaxSize: -1, CaseInsensitive: runtime.GOOS == "windows" || runtime.GOOS == "darwin", // default to true on Windows and Mac, false otherwise + WriteWait: 1000 * time.Millisecond, + ReadWait: 5 * time.Millisecond, } // Node represents either a directory (*Dir) or a file (*File) @@ -202,6 +204,8 @@ type Options struct { CacheMaxSize fs.SizeSuffix CachePollInterval time.Duration CaseInsensitive bool + WriteWait time.Duration // time to wait for in-sequence write + ReadWait time.Duration // time to wait for in-sequence read } // New creates a new VFS and root directory. If opt is nil, then diff --git a/vfs/vfsflags/vfsflags.go b/vfs/vfsflags/vfsflags.go index cf2e910ec..3c8703466 100644 --- a/vfs/vfsflags/vfsflags.go +++ b/vfs/vfsflags/vfsflags.go @@ -33,5 +33,7 @@ func AddFlags(flagSet *pflag.FlagSet) { flags.FVarP(flagSet, DirPerms, "dir-perms", "", "Directory permissions") flags.FVarP(flagSet, FilePerms, "file-perms", "", "File permissions") flags.BoolVarP(flagSet, &Opt.CaseInsensitive, "vfs-case-insensitive", "", Opt.CaseInsensitive, "If a file name not found, find a case insensitive match.") + flags.DurationVarP(flagSet, &Opt.WriteWait, "vfs-write-wait", "", Opt.WriteWait, "Time to wait for in-sequence write before giving error.") + flags.DurationVarP(flagSet, &Opt.ReadWait, "vfs-read-wait", "", Opt.ReadWait, "Time to wait for in-sequence read before seeking.") platformFlags(flagSet) } diff --git a/vfs/write.go b/vfs/write.go index 7939a4823..e45752360 100644 --- a/vfs/write.go +++ b/vfs/write.go @@ -132,7 +132,8 @@ func (fh *WriteFileHandle) writeAt(p []byte, off int64) (n int, err error) { } if fh.offset != off { // Set a background timer so we don't wait forever - timeout := time.NewTimer(10 * time.Second) + maxWait := fh.file.d.vfs.Opt.WriteWait + timeout := time.NewTimer(maxWait) done := make(chan struct{}) abort := int32(0) go func() {