Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions agent/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package agent

import (
"context"
"fmt"
"log/slog"
"os"
"path/filepath"
Expand Down Expand Up @@ -95,6 +96,25 @@ func isDockerSpecialMountpoint(mountpoint string) bool {
return false
}

// uniqueFsStatsKey derives a fsStats map key that does not collide with an
// existing entry by starting from the mountpoint's basename and appending a
// numeric suffix when necessary. Used when the device-derived key would
// otherwise overwrite a different mount (e.g. autofs reporting "systemd-1"
// for every automount target).
func uniqueFsStatsKey(existing map[string]*system.FsStats, mountpoint string) string {
base := filepath.Base(mountpoint)
if base == "" || base == "/" || base == "." {
base = "fs"
}
key := base
for i := 2; ; i++ {
if _, exists := existing[key]; !exists {
return key
}
key = fmt.Sprintf("%s-%d", base, i)
}
}

// registerFilesystemStats resolves the tracked key and stats payload for a
// filesystem before it is inserted into fsStats.
func registerFilesystemStats(existing map[string]*system.FsStats, device, mountpoint string, root bool, customName string, ctx fsRegistrationContext) (string, *system.FsStats, bool) {
Expand Down Expand Up @@ -140,8 +160,16 @@ func registerFilesystemStats(existing map[string]*system.FsStats, device, mountp
}
}

if _, exists := existing[key]; exists {
return "", nil, false
if existingStats, exists := existing[key]; exists {
if existingStats.Mountpoint == mountpoint {
return "", nil, false
}
// Key collides on a different mountpoint. Pseudo-device setups like
// systemd-automount report the same device ("systemd-1") for every
// mount, which would otherwise drop every entry after the first
// (see #1931). Derive a unique key from the mountpoint so each mount
// survives.
key = uniqueFsStatsKey(existing, mountpoint)
}

fsStats := &system.FsStats{Root: root, Mountpoint: mountpoint}
Expand Down
50 changes: 48 additions & 2 deletions agent/disk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ func TestBuildFsStatRegistration(t *testing.T) {
assert.Equal(t, `C:`, key)
})

t.Run("skips existing key", func(t *testing.T) {
t.Run("skips re-registration of the same mountpoint", func(t *testing.T) {
key, stats, ok := registerFilesystemStats(
map[string]*system.FsStats{"sda1": {Mountpoint: "/existing"}},
map[string]*system.FsStats{"sda1": {Mountpoint: "/mnt/data"}},
"/dev/sda1",
"/mnt/data",
false,
Expand All @@ -277,6 +277,52 @@ func TestBuildFsStatRegistration(t *testing.T) {
assert.Empty(t, key)
assert.Nil(t, stats)
})

t.Run("keeps both mounts when a pseudo-device key collides (issue #1931)", func(t *testing.T) {
// systemd-automount reports every mount with device="systemd-1", so
// registering the second entry must not silently drop it.
existing := map[string]*system.FsStats{
"systemd-1": {Mountpoint: "/media/video"},
}
key, stats, ok := registerFilesystemStats(
existing,
"systemd-1",
"/media/backup",
false,
"Backup",
fsRegistrationContext{
isWindows: false,
diskIoCounters: map[string]disk.IOCountersStat{},
},
)

assert.True(t, ok)
assert.NotEqual(t, "systemd-1", key, "key must differ from the colliding entry")
assert.Equal(t, "backup", key)
assert.Equal(t, "/media/backup", stats.Mountpoint)
assert.Equal(t, "Backup", stats.Name)
})

t.Run("derives a suffixed unique key when the mountpoint basename also collides", func(t *testing.T) {
existing := map[string]*system.FsStats{
"systemd-1": {Mountpoint: "/srv/backup"},
"backup": {Mountpoint: "/media/backup"},
}
key, _, ok := registerFilesystemStats(
existing,
"systemd-1",
"/mnt/backup",
false,
"",
fsRegistrationContext{
isWindows: false,
diskIoCounters: map[string]disk.IOCountersStat{},
},
)

assert.True(t, ok)
assert.Equal(t, "backup-2", key)
})
}

func TestAddConfiguredRootFs(t *testing.T) {
Expand Down