forked from TrueCloudLab/rclone
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
4 changed files with 106 additions and 5 deletions
|
@ -275,6 +275,16 @@ func (fsys *FS) Statfs(path string, stat *fuse.Statfs_t) (errc int) {
|
||||||
stat.Bsize = blockSize // Block size
|
stat.Bsize = blockSize // Block size
|
||||||
stat.Namemax = 255 // Maximum file name length?
|
stat.Namemax = 255 // Maximum file name length?
|
||||||
stat.Frsize = blockSize // Fragment size, smallest addressable data size in the file system.
|
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
|
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.Bsize = blockSize // Block size
|
||||||
resp.Namelen = 255 // Maximum file name length?
|
resp.Namelen = 255 // Maximum file name length?
|
||||||
resp.Frsize = blockSize // Fragment size, smallest addressable data size in the file system.
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
41
vfs/vfs.go
41
vfs/vfs.go
|
@ -24,6 +24,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -170,6 +171,9 @@ type VFS struct {
|
||||||
Opt Options
|
Opt Options
|
||||||
cache *cache
|
cache *cache
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
usageMu sync.Mutex
|
||||||
|
usageTime time.Time
|
||||||
|
usage *fs.Usage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options is options for creating the vfs
|
// Options is options for creating the vfs
|
||||||
|
@ -452,3 +456,40 @@ func (vfs *VFS) Rename(oldName, newName string) error {
|
||||||
}
|
}
|
||||||
return nil
|
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")
|
err = vfs.Rename("file0", "not found/file0")
|
||||||
assert.Equal(t, os.ErrNotExist, err)
|
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 a new issue