From 0bf981278ed619773bfc21e5150aba4c7090ba77 Mon Sep 17 00:00:00 2001 From: Tamer Fahmy Date: Tue, 26 Sep 2017 03:46:19 +0200 Subject: [PATCH] Provide the correct free block size volume/disk information (#4943) On *NIX platforms the statfs(2) system call returns a struct containing both the free blocks in the filesystem (Statfs_t.Bfree) and the free blocks available to the unprivileged or non-superuser (Statfs_t.Bavail). The `Bfree` and `Bavail` fields (with `Bfree >= Bavail`) will be set to different values on e.g. filesystems such as ext4 that reserve a certain percentage of the filesystem blocks which may only be allocated by admnistrative privileged processes. The calculations for the `Total` disk space need to subtract the difference between the `Bfree` and `Bavail` fields for it to correctly show the total available storage space available for unprivileged users. This implicitly fixes a bug where the `Used = Total - Free` calculation yielded different (and also incorrect) results for identical contents stored when only the sizes of the disks or backing volumes differed. (as can be witnessed in the `Used:` value displayed in the Minio browser) See: - https://wiki.archlinux.org/index.php/ext4#Reserved_blocks - http://man7.org/linux/man-pages/man2/statfs.2.html - https://man.openbsd.org/statfs - http://lingrok.org/xref/coreutils/src/df.c#893 --- pkg/disk/stat_bsd.go | 14 ++++++++------ pkg/disk/stat_linux.go | 14 ++++++++------ pkg/disk/stat_openbsd.go | 14 ++++++++------ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/pkg/disk/stat_bsd.go b/pkg/disk/stat_bsd.go index 0d803f0e7..3dee0d455 100644 --- a/pkg/disk/stat_bsd.go +++ b/pkg/disk/stat_bsd.go @@ -29,11 +29,13 @@ func GetInfo(path string) (info Info, err error) { if err != nil { return Info{}, err } - info = Info{} - info.Total = uint64(s.Bsize) * uint64(s.Blocks) - info.Free = uint64(s.Bsize) * uint64(s.Bavail) - info.Files = uint64(s.Files) - info.Ffree = uint64(s.Ffree) - info.FSType = getFSType(s.Fstypename) + fsReservedBlocks := uint64(s.Bfree) - uint64(s.Bavail) + info = Info{ + Total: uint64(s.Bsize) * (uint64(s.Blocks) - fsReservedBlocks), + Free: uint64(s.Bsize) * uint64(s.Bavail), + Files: uint64(s.Files), + Ffree: uint64(s.Ffree), + FSType: getFSType(s.Fstypename), + } return info, nil } diff --git a/pkg/disk/stat_linux.go b/pkg/disk/stat_linux.go index 1ecfc48ee..a4de8f9ac 100644 --- a/pkg/disk/stat_linux.go +++ b/pkg/disk/stat_linux.go @@ -29,11 +29,13 @@ func GetInfo(path string) (info Info, err error) { if err != nil { return Info{}, err } - info = Info{} - info.Total = uint64(s.Bsize) * uint64(s.Blocks) - info.Free = uint64(s.Bsize) * uint64(s.Bavail) - info.Files = uint64(s.Files) - info.Ffree = uint64(s.Ffree) - info.FSType = getFSType(int64(s.Type)) + fsReservedBlocks := uint64(s.Bfree) - uint64(s.Bavail) + info = Info{ + Total: uint64(s.Bsize) * (uint64(s.Blocks) - fsReservedBlocks), + Free: uint64(s.Bsize) * uint64(s.Bavail), + Files: uint64(s.Files), + Ffree: uint64(s.Ffree), + FSType: getFSType(int64(s.Type)), + } return info, nil } diff --git a/pkg/disk/stat_openbsd.go b/pkg/disk/stat_openbsd.go index b341dec93..eabb368fc 100644 --- a/pkg/disk/stat_openbsd.go +++ b/pkg/disk/stat_openbsd.go @@ -29,11 +29,13 @@ func GetInfo(path string) (info Info, err error) { if err != nil { return Info{}, err } - info = Info{} - info.Total = uint64(s.F_bsize) * uint64(s.F_blocks) - info.Free = uint64(s.F_bsize) * uint64(s.F_bavail) - info.Files = uint64(s.F_files) - info.Ffree = uint64(s.F_ffree) - info.FSType = getFSType(s.F_fstypename) + fsReservedBlocks := uint64(s.F_bfree) - uint64(s.F_bavail) + info = Info{ + Total: uint64(s.F_bsize) * (uint64(s.F_blocks) - fsReservedBlocks), + Free: uint64(s.F_bsize) * uint64(s.F_bavail), + Files: uint64(s.F_files), + Ffree: uint64(s.F_ffree), + FSType: getFSType(s.F_fstypename), + } return info, nil }