From 174ca22936689e2491cd278a8a6d90aac4999c2f Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 26 Jun 2018 09:26:34 +0100 Subject: [PATCH] mount,cmount: clip the number of blocks to 2^32-1 on macOS OSX FUSE only supports 32 bit number of blocks which means that block counts have been wrapping. This causes f_bavail to be 0 which in turn causes problems with programs like borg backup. Fixes #2356 --- cmd/cmount/fs.go | 10 +++++----- cmd/mount/fs.go | 4 ++++ cmd/mountlib/mount.go | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/cmd/cmount/fs.go b/cmd/cmount/fs.go index 83e0f819c..b0a5e511e 100644 --- a/cmd/cmount/fs.go +++ b/cmd/cmount/fs.go @@ -8,11 +8,11 @@ import ( "io" "os" "path" - "runtime" "sync" "time" "github.com/billziss-gh/cgofuse/fuse" + "github.com/ncw/rclone/cmd/mountlib" "github.com/ncw/rclone/fs" "github.com/ncw/rclone/fs/log" "github.com/ncw/rclone/vfs" @@ -263,10 +263,7 @@ func (fsys *FS) Releasedir(path string, fh uint64) (errc int) { func (fsys *FS) Statfs(path string, stat *fuse.Statfs_t) (errc int) { defer log.Trace(path, "")("stat=%+v, errc=%d", stat, &errc) const blockSize = 4096 - fsBlocks := uint64(1 << 50) - if runtime.GOOS == "windows" { - fsBlocks = (1 << 43) - 1 - } + const fsBlocks = (1 << 50) / blockSize stat.Blocks = fsBlocks // Total data blocks in file system. stat.Bfree = fsBlocks // Free blocks in file system. stat.Bavail = fsBlocks // Free blocks in file system if you're not root. @@ -285,6 +282,9 @@ func (fsys *FS) Statfs(path string, stat *fuse.Statfs_t) (errc int) { if free >= 0 { stat.Bavail = uint64(free) / blockSize } + mountlib.ClipBlocks(&stat.Blocks) + mountlib.ClipBlocks(&stat.Bfree) + mountlib.ClipBlocks(&stat.Bavail) return 0 } diff --git a/cmd/mount/fs.go b/cmd/mount/fs.go index caab6a060..68e7cc5b0 100644 --- a/cmd/mount/fs.go +++ b/cmd/mount/fs.go @@ -9,6 +9,7 @@ import ( "bazil.org/fuse" fusefs "bazil.org/fuse/fs" + "github.com/ncw/rclone/cmd/mountlib" "github.com/ncw/rclone/fs" "github.com/ncw/rclone/fs/log" "github.com/ncw/rclone/vfs" @@ -72,6 +73,9 @@ func (f *FS) Statfs(ctx context.Context, req *fuse.StatfsRequest, resp *fuse.Sta if free >= 0 { resp.Bavail = uint64(free) / blockSize } + mountlib.ClipBlocks(&resp.Blocks) + mountlib.ClipBlocks(&resp.Bfree) + mountlib.ClipBlocks(&resp.Bavail) return nil } diff --git a/cmd/mountlib/mount.go b/cmd/mountlib/mount.go index e9f6e7456..f3fe2ae4f 100644 --- a/cmd/mountlib/mount.go +++ b/cmd/mountlib/mount.go @@ -293,3 +293,22 @@ be copied to the vfs cache before opening with --vfs-cache-mode full. return commandDefintion } + +// ClipBlocks clips the blocks pointed to to the OS max +func ClipBlocks(b *uint64) { + var max uint64 + switch runtime.GOOS { + case "windows": + max = (1 << 43) - 1 + case "darwin": + // OSX FUSE only supports 32 bit number of blocks + // https://github.com/osxfuse/osxfuse/issues/396 + max = (1 << 32) - 1 + default: + // no clipping + return + } + if *b > max { + *b = max + } +}