mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 09:41:44 +08:00
vfs,mount,cmount: use About to return the correct disk total/used/free
Disks total, used, free now shows correctly for mount and cmount (eg `df` for Unix or in the Windows explorer).
This commit is contained in:
parent
ef3bcec76c
commit
2b855751fc
|
@ -275,6 +275,16 @@ func (fsys *FS) Statfs(path string, stat *fuse.Statfs_t) (errc int) {
|
|||
stat.Bsize = blockSize // Block size
|
||||
stat.Namemax = 255 // Maximum file name length?
|
||||
stat.Frsize = blockSize // Fragment size, smallest addressable data size in the file system.
|
||||
total, used, free := fsys.VFS.Statfs()
|
||||
if total >= 0 {
|
||||
stat.Blocks = uint64(total) / blockSize
|
||||
}
|
||||
if used >= 0 {
|
||||
stat.Bfree = stat.Blocks - uint64(used)/blockSize
|
||||
}
|
||||
if free >= 0 {
|
||||
stat.Bavail = uint64(free) / blockSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,16 @@ func (f *FS) Statfs(ctx context.Context, req *fuse.StatfsRequest, resp *fuse.Sta
|
|||
resp.Bsize = blockSize // Block size
|
||||
resp.Namelen = 255 // Maximum file name length?
|
||||
resp.Frsize = blockSize // Fragment size, smallest addressable data size in the file system.
|
||||
total, used, free := f.VFS.Statfs()
|
||||
if total >= 0 {
|
||||
resp.Blocks = uint64(total) / blockSize
|
||||
}
|
||||
if used >= 0 {
|
||||
resp.Bfree = resp.Blocks - uint64(used)/blockSize
|
||||
}
|
||||
if free >= 0 {
|
||||
resp.Bavail = uint64(free) / blockSize
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
51
vfs/vfs.go
51
vfs/vfs.go
|
@ -24,6 +24,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
|
@ -165,11 +166,14 @@ var (
|
|||
|
||||
// VFS represents the top level filing system
|
||||
type VFS struct {
|
||||
f fs.Fs
|
||||
root *Dir
|
||||
Opt Options
|
||||
cache *cache
|
||||
cancel context.CancelFunc
|
||||
f fs.Fs
|
||||
root *Dir
|
||||
Opt Options
|
||||
cache *cache
|
||||
cancel context.CancelFunc
|
||||
usageMu sync.Mutex
|
||||
usageTime time.Time
|
||||
usage *fs.Usage
|
||||
}
|
||||
|
||||
// Options is options for creating the vfs
|
||||
|
@ -452,3 +456,40 @@ func (vfs *VFS) Rename(oldName, newName string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Statfs returns into about the filing system if known
|
||||
//
|
||||
// The values will be -1 if they aren't known
|
||||
//
|
||||
// This information is cached for the DirCacheTime interval
|
||||
func (vfs *VFS) Statfs() (total, used, free int64) {
|
||||
// defer log.Trace("/", "")("total=%d, used=%d, free=%d", &total, &used, &free)
|
||||
vfs.usageMu.Lock()
|
||||
defer vfs.usageMu.Unlock()
|
||||
total, used, free = -1, -1, -1
|
||||
doAbout := vfs.f.Features().About
|
||||
if doAbout == nil {
|
||||
return
|
||||
}
|
||||
if vfs.usageTime.IsZero() || time.Since(vfs.usageTime) >= vfs.Opt.DirCacheTime {
|
||||
var err error
|
||||
vfs.usage, err = doAbout()
|
||||
vfs.usageTime = time.Now()
|
||||
if err != nil {
|
||||
fs.Errorf(vfs.f, "Statfs failed: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if u := vfs.usage; u != nil {
|
||||
if u.Total != nil {
|
||||
total = *u.Total
|
||||
}
|
||||
if u.Free != nil {
|
||||
free = *u.Free
|
||||
}
|
||||
if u.Used != nil {
|
||||
used = *u.Used
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -251,3 +251,43 @@ func TestVFSRename(t *testing.T) {
|
|||
err = vfs.Rename("file0", "not found/file0")
|
||||
assert.Equal(t, os.ErrNotExist, err)
|
||||
}
|
||||
|
||||
func TestVFSStatfs(t *testing.T) {
|
||||
r := fstest.NewRun(t)
|
||||
defer r.Finalise()
|
||||
vfs := New(r.Fremote, nil)
|
||||
|
||||
// pre-conditions
|
||||
assert.Nil(t, vfs.usage)
|
||||
assert.True(t, vfs.usageTime.IsZero())
|
||||
|
||||
// read
|
||||
total, used, free := vfs.Statfs()
|
||||
require.NotNil(t, vfs.usage)
|
||||
assert.False(t, vfs.usageTime.IsZero())
|
||||
if vfs.usage.Total != nil {
|
||||
assert.Equal(t, *vfs.usage.Total, total)
|
||||
} else {
|
||||
assert.Equal(t, -1, total)
|
||||
}
|
||||
if vfs.usage.Free != nil {
|
||||
assert.Equal(t, *vfs.usage.Free, free)
|
||||
} else {
|
||||
assert.Equal(t, -1, free)
|
||||
}
|
||||
if vfs.usage.Used != nil {
|
||||
assert.Equal(t, *vfs.usage.Used, used)
|
||||
} else {
|
||||
assert.Equal(t, -1, used)
|
||||
}
|
||||
|
||||
// read cached
|
||||
oldUsage := vfs.usage
|
||||
oldTime := vfs.usageTime
|
||||
total2, used2, free2 := vfs.Statfs()
|
||||
assert.Equal(t, oldUsage, vfs.usage)
|
||||
assert.Equal(t, total, total2)
|
||||
assert.Equal(t, used, used2)
|
||||
assert.Equal(t, free, free2)
|
||||
assert.Equal(t, oldTime, vfs.usageTime)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user