mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-05-17 00:26:36 +03:00
lib/fs: Add total disk space retrieval (#9523)
Extends the disk space monitoring functionality by adding support for retrieving total disk capacity in addition to free space. Related: https://github.com/VictoriaMetrics/VictoriaLogs/issues/513 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
47
lib/fs/fs.go
47
lib/fs/fs.go
@@ -286,31 +286,56 @@ const FlockFilename = "flock.lock"
|
||||
// MustGetFreeSpace returns free space for the given directory path.
|
||||
func MustGetFreeSpace(path string) uint64 {
|
||||
// Try obtaining cached value at first.
|
||||
freeSpaceMapLock.Lock()
|
||||
defer freeSpaceMapLock.Unlock()
|
||||
diskSpaceMapLock.Lock()
|
||||
defer diskSpaceMapLock.Unlock()
|
||||
|
||||
e, ok := freeSpaceMap[path]
|
||||
e, ok := diskSpaceMap[path]
|
||||
if ok && fasttime.UnixTimestamp()-e.updateTime < 2 {
|
||||
// Fast path - the entry is fresh.
|
||||
return e.freeSpace
|
||||
return e.free
|
||||
}
|
||||
|
||||
// Slow path.
|
||||
// Determine the amount of free space at path.
|
||||
e.freeSpace = mustGetFreeSpace(path)
|
||||
e = updateDiskSpaceLocked(path)
|
||||
return e.free
|
||||
}
|
||||
|
||||
// MustGetTotalSpace returns the total disk space for the given directory path.
|
||||
func MustGetTotalSpace(path string) uint64 {
|
||||
// Try obtaining cached value at first.
|
||||
defer diskSpaceMapLock.Unlock()
|
||||
|
||||
e, ok := diskSpaceMap[path]
|
||||
if ok && fasttime.UnixTimestamp()-e.updateTime < 2 {
|
||||
// Fast path - the entry is fresh.
|
||||
return e.total
|
||||
}
|
||||
|
||||
// Slow path.
|
||||
// Determine the amount of total space at path.
|
||||
e = updateDiskSpaceLocked(path)
|
||||
return e.total
|
||||
}
|
||||
|
||||
func updateDiskSpaceLocked(path string) diskSpaceEntry {
|
||||
var e diskSpaceEntry
|
||||
e.total, e.free = mustGetDiskSpace(path)
|
||||
e.updateTime = fasttime.UnixTimestamp()
|
||||
freeSpaceMap[path] = e
|
||||
return e.freeSpace
|
||||
diskSpaceMap[path] = e
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
freeSpaceMap = make(map[string]freeSpaceEntry)
|
||||
freeSpaceMapLock sync.Mutex
|
||||
diskSpaceMap = make(map[string]diskSpaceEntry)
|
||||
diskSpaceMapLock sync.Mutex
|
||||
)
|
||||
|
||||
type freeSpaceEntry struct {
|
||||
type diskSpaceEntry struct {
|
||||
updateTime uint64
|
||||
freeSpace uint64
|
||||
free uint64
|
||||
total uint64
|
||||
}
|
||||
|
||||
// IsDirOrSymlink returns true if de is directory or symlink.
|
||||
|
||||
@@ -10,6 +10,11 @@ func freeSpace(stat statfs_t) uint64 {
|
||||
return uint64(stat.Bavail) * uint64(stat.Bsize)
|
||||
}
|
||||
|
||||
// totalSpace returns the total capacity of the filesystem in bytes.
|
||||
func totalSpace(stat statfs_t) uint64 {
|
||||
return uint64(stat.Blocks) * uint64(stat.Bsize)
|
||||
}
|
||||
|
||||
func statfs(path string, buf *statfs_t) (err error) {
|
||||
return unix.Statvfs(path, buf)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,11 @@ func freeSpace(stat statfs_t) uint64 {
|
||||
return uint64(stat.Bavail) * uint64(stat.Bsize)
|
||||
}
|
||||
|
||||
// totalSpace returns the total capacity of the filesystem described by stat in bytes.
|
||||
func totalSpace(stat statfs_t) uint64 {
|
||||
return uint64(stat.Blocks) * uint64(stat.Bsize)
|
||||
}
|
||||
|
||||
func statfs(path string, stat *statfs_t) (err error) {
|
||||
return unix.Statfs(path, stat)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ func freeSpace(stat statfs_t) uint64 {
|
||||
return uint64(stat.F_bavail) * uint64(stat.F_bsize)
|
||||
}
|
||||
|
||||
// totalSpace returns the total capacity of the filesystem in bytes.
|
||||
func totalSpace(stat statfs_t) uint64 {
|
||||
return uint64(stat.F_blocks) * uint64(stat.F_bsize)
|
||||
}
|
||||
|
||||
func statfs(path string, stat *statfs_t) (err error) {
|
||||
return unix.Statfs(path, stat)
|
||||
}
|
||||
|
||||
@@ -48,12 +48,19 @@ func createFlockFile(flockFile string) (*os.File, error) {
|
||||
return flockF, nil
|
||||
}
|
||||
|
||||
func mustGetFreeSpace(path string) uint64 {
|
||||
func mustGetDiskSpace(path string) (total, free uint64) {
|
||||
var stat unix.Statvfs_t
|
||||
if err := unix.Statvfs(path, &stat); err != nil {
|
||||
logger.Panicf("FATAL: cannot determine free disk space on %q: %s", path, err)
|
||||
}
|
||||
return freeSpace(stat)
|
||||
total = totalSpace(stat)
|
||||
free = freeSpace(stat)
|
||||
return
|
||||
}
|
||||
|
||||
// totalSpace returns the total capacity of the filesystem in bytes.
|
||||
func totalSpace(stat unix.Statvfs_t) uint64 {
|
||||
return uint64(stat.Blocks) * uint64(stat.Bsize)
|
||||
}
|
||||
|
||||
func freeSpace(stat unix.Statvfs_t) uint64 {
|
||||
|
||||
@@ -43,10 +43,13 @@ func createFlockFile(flockFile string) (*os.File, error) {
|
||||
return flockF, nil
|
||||
}
|
||||
|
||||
func mustGetFreeSpace(path string) uint64 {
|
||||
func mustGetDiskSpace(path string) (total, free uint64) {
|
||||
var stat statfs_t
|
||||
if err := statfs(path, &stat); err != nil {
|
||||
logger.Panicf("FATAL: cannot determine free disk space on %q: %s", path, err)
|
||||
}
|
||||
return freeSpace(stat)
|
||||
|
||||
total = totalSpace(stat)
|
||||
free = freeSpace(stat)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -102,14 +102,13 @@ func mUnmap(data []byte) error {
|
||||
return os.NewSyscallError("CloseHandle", errno)
|
||||
}
|
||||
|
||||
func mustGetFreeSpace(path string) uint64 {
|
||||
var freeBytes uint64
|
||||
func mustGetDiskSpace(path string) (total, free uint64) {
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexw
|
||||
err := windows.GetDiskFreeSpaceEx(windows.StringToUTF16Ptr(path), &freeBytes, nil, nil)
|
||||
err := windows.GetDiskFreeSpaceEx(windows.StringToUTF16Ptr(path), &free, &total, nil)
|
||||
if err != nil {
|
||||
logger.Panicf("FATAL: cannot get free space for %q : %s", path, err)
|
||||
}
|
||||
return freeBytes
|
||||
return total, free
|
||||
}
|
||||
|
||||
// stub
|
||||
|
||||
Reference in New Issue
Block a user