cmount: use ReaddirPlus on Windows to improve directory listing performance

Before this change Windows would read a directory then immedately stat
every item in the directory.

After this change we return the stat information along with the
directory which stops so many callbacks.
This commit is contained in:
Nick Craig-Wood 2020-05-01 18:33:47 +01:00
parent 6ca7198f57
commit d260238f99
2 changed files with 18 additions and 1 deletions

View file

@ -251,7 +251,14 @@ func (fsys *FS) Readdir(dirPath string,
fs.Errorf(dirPath, "Name too long (%d bytes) for FUSE, skipping: %s", len(name), name) fs.Errorf(dirPath, "Name too long (%d bytes) for FUSE, skipping: %s", len(name), name)
continue continue
} }
fill(name, nil, 0) if usingReaddirPlus {
// We have called host.SetCapReaddirPlus() so supply the stat information
var stat fuse.Stat_t
_ = fsys.stat(node, &stat) // not capable of returning an error
fill(name, &stat, 0)
} else {
fill(name, nil, 0)
}
} }
} }
itemsRead = len(items) itemsRead = len(items)

View file

@ -26,6 +26,13 @@ import (
"github.com/rclone/rclone/vfs/vfsflags" "github.com/rclone/rclone/vfs/vfsflags"
) )
const (
// SetCapReaddirPlus informs the host that the hosted file system has the readdir-plus
// capability [Windows only]. A file system that has the readdir-plus capability can send
// full stat information during Readdir, thus avoiding extraneous Getattr calls.
usingReaddirPlus = runtime.GOOS == "windows"
)
func init() { func init() {
name := "cmount" name := "cmount"
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
@ -142,6 +149,9 @@ func mount(f fs.Fs, mountpoint string) (*vfs.VFS, <-chan error, func() error, er
// Create underlying FS // Create underlying FS
fsys := NewFS(f) fsys := NewFS(f)
host := fuse.NewFileSystemHost(fsys) host := fuse.NewFileSystemHost(fsys)
if usingReaddirPlus {
host.SetCapReaddirPlus(true)
}
// Create options // Create options
options := mountOptions(f.Name()+":"+f.Root(), mountpoint) options := mountOptions(f.Name()+":"+f.Root(), mountpoint)