vfs: fix very high load caused by slow directory listings
In this commit (released in v1.52.0)
6ca7198f
mount: fix disappearing cwd problem
SetSys was introduced to cache node lookups.
Unfortunately taking the vfs.(*Dir) lock in SetSys causes any FUSE
operations on a directory to pile up behind slow directory listings.
In some situations this leads to very high load.
This commit fixes it by using atomic operations to read and write the
Sys value make it independent of the lock.
See: https://forum.rclone.org/t/high-cpu-load-with-rclone-mount/17604
See: #4104
This commit is contained in:
parent
59770a4953
commit
2adc057d95
2 changed files with 7 additions and 14 deletions
11
vfs/dir.go
11
vfs/dir.go
|
@ -7,6 +7,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
@ -33,7 +34,7 @@ type Dir struct {
|
|||
read time.Time // time directory entry last read
|
||||
items map[string]Node // directory entries - can be empty but not nil
|
||||
virtual map[string]vState // virtual directory entries - may be nil
|
||||
sys interface{} // user defined info to be attached here
|
||||
sys atomic.Value // user defined info to be attached here
|
||||
}
|
||||
|
||||
//go:generate stringer -type=vState
|
||||
|
@ -105,16 +106,12 @@ func (d *Dir) Path() (name string) {
|
|||
|
||||
// Sys returns underlying data source (can be nil) - satisfies Node interface
|
||||
func (d *Dir) Sys() interface{} {
|
||||
d.mu.RLock()
|
||||
defer d.mu.RUnlock()
|
||||
return d.sys
|
||||
return d.sys.Load()
|
||||
}
|
||||
|
||||
// SetSys sets the underlying data source (can be nil) - satisfies Node interface
|
||||
func (d *Dir) SetSys(x interface{}) {
|
||||
d.mu.Lock()
|
||||
d.sys = x
|
||||
d.mu.Unlock()
|
||||
d.sys.Store(x)
|
||||
}
|
||||
|
||||
// Inode returns the inode number - satisfies Node interface
|
||||
|
|
10
vfs/file.go
10
vfs/file.go
|
@ -48,7 +48,7 @@ type File struct {
|
|||
pendingModTime time.Time // will be applied once o becomes available, i.e. after file was written
|
||||
pendingRenameFun func(ctx context.Context) error // will be run/renamed after all writers close
|
||||
appendMode bool // file was opened with O_APPEND
|
||||
sys interface{} // user defined info to be attached here
|
||||
sys atomic.Value // user defined info to be attached here
|
||||
|
||||
muRW sync.Mutex // synchronize RWFileHandle.openPending(), RWFileHandle.close() and File.Remove
|
||||
}
|
||||
|
@ -122,16 +122,12 @@ func (f *File) Path() string {
|
|||
|
||||
// Sys returns underlying data source (can be nil) - satisfies Node interface
|
||||
func (f *File) Sys() interface{} {
|
||||
f.mu.RLock()
|
||||
defer f.mu.RUnlock()
|
||||
return f.sys
|
||||
return f.sys.Load()
|
||||
}
|
||||
|
||||
// SetSys sets the underlying data source (can be nil) - satisfies Node interface
|
||||
func (f *File) SetSys(x interface{}) {
|
||||
f.mu.Lock()
|
||||
f.sys = x
|
||||
f.mu.Unlock()
|
||||
f.sys.Store(x)
|
||||
}
|
||||
|
||||
// Inode returns the inode number - satisfies Node interface
|
||||
|
|
Loading…
Reference in a new issue