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
This commit is contained in:
Nick Craig-Wood 2020-02-04 10:56:00 +00:00
parent e3c11c9ca1
commit 393b94bb70
4 changed files with 12 additions and 4 deletions

View File

@ -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) { if gap := off - fh.offset; gap > 0 && gap < int64(8*maxBuf) {
// Set a background timer so we don't wait for long // Set a background timer so we don't wait for long
// Waits here potentially affect all seeks so need to keep them short // 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 // The default time here was made by finding the
// that didn't cause seeks. // smallest when mounting a local backend that didn't
const maxWait = 5 * time.Millisecond // cause seeks.
maxWait := fh.file.d.vfs.Opt.ReadWait
timeout := time.NewTimer(maxWait) timeout := time.NewTimer(maxWait)
done := make(chan struct{}) done := make(chan struct{})
abort := int32(0) abort := int32(0)

View File

@ -53,6 +53,8 @@ var DefaultOpt = Options{
ChunkSizeLimit: -1, ChunkSizeLimit: -1,
CacheMaxSize: -1, CacheMaxSize: -1,
CaseInsensitive: runtime.GOOS == "windows" || runtime.GOOS == "darwin", // default to true on Windows and Mac, false otherwise 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) // Node represents either a directory (*Dir) or a file (*File)
@ -202,6 +204,8 @@ type Options struct {
CacheMaxSize fs.SizeSuffix CacheMaxSize fs.SizeSuffix
CachePollInterval time.Duration CachePollInterval time.Duration
CaseInsensitive bool 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 // New creates a new VFS and root directory. If opt is nil, then

View File

@ -33,5 +33,7 @@ func AddFlags(flagSet *pflag.FlagSet) {
flags.FVarP(flagSet, DirPerms, "dir-perms", "", "Directory permissions") flags.FVarP(flagSet, DirPerms, "dir-perms", "", "Directory permissions")
flags.FVarP(flagSet, FilePerms, "file-perms", "", "File 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.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) platformFlags(flagSet)
} }

View File

@ -132,7 +132,8 @@ func (fh *WriteFileHandle) writeAt(p []byte, off int64) (n int, err error) {
} }
if fh.offset != off { if fh.offset != off {
// Set a background timer so we don't wait forever // 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{}) done := make(chan struct{})
abort := int32(0) abort := int32(0)
go func() { go func() {