github.com/grafana/pyroscope@v1.18.0/pkg/util/disk/disk.go (about) 1 //go:build !windows 2 3 package diskutil 4 5 import ( 6 "fmt" 7 "math" 8 9 "golang.org/x/sys/unix" 10 ) 11 12 type volumeChecker struct { 13 minFreeDisk uint64 14 minDiskAvailablePercentage float64 15 } 16 17 func NewVolumeChecker(minFreeDisk uint64, minDiskAvailablePercentage float64) VolumeChecker { 18 return &volumeChecker{ 19 minFreeDisk: minFreeDisk, 20 minDiskAvailablePercentage: minDiskAvailablePercentage, 21 } 22 } 23 24 func (v *volumeChecker) HasHighDiskUtilization(path string) (*VolumeStats, error) { 25 var stat unix.Statfs_t 26 if err := unix.Statfs(path, &stat); err != nil { 27 return nil, err 28 } 29 30 //nolint:unconvert // In BSD family (except OpenBSD), the type of stat.Bavail is int64. 31 avail := uint64(stat.Bavail) 32 isValid := avail&math.MaxInt64 == avail && stat.Blocks > 0 33 if !isValid { 34 return nil, fmt.Errorf("invalid statfs values: %+v", stat) 35 } 36 37 // available means accessible to the current user, while free means bytes 38 // for privileged users. (Linux sometimes reserves some space for root) 39 var ( 40 stats = VolumeStats{ 41 BytesAvailable: avail * uint64(stat.Bsize), 42 } 43 percentageAvailable = float64(avail) / float64(stat.Blocks*uint64(stat.Bsize)) 44 ) 45 46 // if bytes available is bigger than minFreeDisk => not in high disk utilization 47 if stats.BytesAvailable >= v.minFreeDisk { 48 return &stats, nil 49 } 50 51 // no in high disk utilization when more than the constant 52 if percentageAvailable > v.minDiskAvailablePercentage { 53 return &stats, nil 54 } 55 56 stats.HighDiskUtilization = true 57 return &stats, nil 58 }