mirror of
https://github.com/henrygd/beszel.git
synced 2026-03-21 21:26:16 +01:00
fix: dedupe root-mirrored extra filesystems during disk discovery (#1428)
This commit is contained in:
@@ -197,9 +197,60 @@ func (a *Agent) initializeDiskInfo() {
|
|||||||
a.fsStats[rootKey] = &system.FsStats{Root: true, Mountpoint: rootMountPoint}
|
a.fsStats[rootKey] = &system.FsStats{Root: true, Mountpoint: rootMountPoint}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.pruneDuplicateRootExtraFilesystems()
|
||||||
a.initializeDiskIoStats(diskIoCounters)
|
a.initializeDiskIoStats(diskIoCounters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes extra filesystems that mirror root usage (https://github.com/henrygd/beszel/issues/1428).
|
||||||
|
func (a *Agent) pruneDuplicateRootExtraFilesystems() {
|
||||||
|
var rootMountpoint string
|
||||||
|
for _, stats := range a.fsStats {
|
||||||
|
if stats != nil && stats.Root {
|
||||||
|
rootMountpoint = stats.Mountpoint
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rootMountpoint == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rootUsage, err := disk.Usage(rootMountpoint)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for name, stats := range a.fsStats {
|
||||||
|
if stats == nil || stats.Root {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
extraUsage, err := disk.Usage(stats.Mountpoint)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if hasSameDiskUsage(rootUsage, extraUsage) {
|
||||||
|
slog.Info("Ignoring duplicate FS", "name", name, "mount", stats.Mountpoint)
|
||||||
|
delete(a.fsStats, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasSameDiskUsage compares root/extra usage with a small byte tolerance.
|
||||||
|
func hasSameDiskUsage(a, b *disk.UsageStat) bool {
|
||||||
|
if a == nil || b == nil || a.Total == 0 || b.Total == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Allow minor drift between sequential disk usage calls.
|
||||||
|
const toleranceBytes uint64 = 16 * 1024 * 1024
|
||||||
|
return withinUsageTolerance(a.Total, b.Total, toleranceBytes) &&
|
||||||
|
withinUsageTolerance(a.Used, b.Used, toleranceBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// withinUsageTolerance reports whether two byte values differ by at most tolerance.
|
||||||
|
func withinUsageTolerance(a, b, tolerance uint64) bool {
|
||||||
|
if a >= b {
|
||||||
|
return a-b <= tolerance
|
||||||
|
}
|
||||||
|
return b-a <= tolerance
|
||||||
|
}
|
||||||
|
|
||||||
// Returns matching device from /proc/diskstats.
|
// Returns matching device from /proc/diskstats.
|
||||||
// bool is true if a match was found.
|
// bool is true if a match was found.
|
||||||
func findIoDevice(filesystem string, diskIoCounters map[string]disk.IOCountersStat) (string, bool) {
|
func findIoDevice(filesystem string, diskIoCounters map[string]disk.IOCountersStat) (string, bool) {
|
||||||
|
|||||||
@@ -372,3 +372,37 @@ func TestDiskUsageCaching(t *testing.T) {
|
|||||||
"lastDiskUsageUpdate should be refreshed when cache expires")
|
"lastDiskUsageUpdate should be refreshed when cache expires")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHasSameDiskUsage(t *testing.T) {
|
||||||
|
const toleranceBytes uint64 = 16 * 1024 * 1024
|
||||||
|
|
||||||
|
t.Run("returns true when totals and usage are equal", func(t *testing.T) {
|
||||||
|
a := &disk.UsageStat{Total: 100 * 1024 * 1024 * 1024, Used: 42 * 1024 * 1024 * 1024}
|
||||||
|
b := &disk.UsageStat{Total: 100 * 1024 * 1024 * 1024, Used: 42 * 1024 * 1024 * 1024}
|
||||||
|
assert.True(t, hasSameDiskUsage(a, b))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns true within tolerance", func(t *testing.T) {
|
||||||
|
a := &disk.UsageStat{Total: 100 * 1024 * 1024 * 1024, Used: 42 * 1024 * 1024 * 1024}
|
||||||
|
b := &disk.UsageStat{
|
||||||
|
Total: a.Total + toleranceBytes - 1,
|
||||||
|
Used: a.Used - toleranceBytes + 1,
|
||||||
|
}
|
||||||
|
assert.True(t, hasSameDiskUsage(a, b))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns false when total exceeds tolerance", func(t *testing.T) {
|
||||||
|
a := &disk.UsageStat{Total: 100 * 1024 * 1024 * 1024, Used: 42 * 1024 * 1024 * 1024}
|
||||||
|
b := &disk.UsageStat{
|
||||||
|
Total: a.Total + toleranceBytes + 1,
|
||||||
|
Used: a.Used,
|
||||||
|
}
|
||||||
|
assert.False(t, hasSameDiskUsage(a, b))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns false for nil or zero total", func(t *testing.T) {
|
||||||
|
assert.False(t, hasSameDiskUsage(nil, &disk.UsageStat{Total: 1, Used: 1}))
|
||||||
|
assert.False(t, hasSameDiskUsage(&disk.UsageStat{Total: 1, Used: 1}, nil))
|
||||||
|
assert.False(t, hasSameDiskUsage(&disk.UsageStat{Total: 0, Used: 0}, &disk.UsageStat{Total: 1, Used: 1}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user