Skip to content
Merged
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
3 changes: 2 additions & 1 deletion block/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ type DeviceProperties struct {
Vendor string
// Serial /sys/block/<dev>/device/serial.
Serial string
// Modalias /sys/block/<dev>/device/modalias.
// Modalias from /sys/block/<dev>/device/modalias, falling back to
// /sys/block/<dev>/device/device/modalias when the former is absent (common on NVMe).
Modalias string
// WWID /sys/block/<dev>/wwid.
WWID string
Expand Down
12 changes: 11 additions & 1 deletion block/device_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ func (d *Device) GetProperties() (*DeviceProperties, error) {
Model: readSysFsFile(filepath.Join(sysFsPath, "device", "model")),
Vendor: readSysFsFile(filepath.Join(sysFsPath, "device", "vendor")),
Serial: readSysFsFile(filepath.Join(sysFsPath, "serial")),
Modalias: readSysFsFile(filepath.Join(sysFsPath, "device", "modalias")),
Modalias: readBlockDeviceModalias(sysFsPath),
WWID: readSysFsFile(filepath.Join(sysFsPath, "wwid")),
UUID: readSysFsFile(filepath.Join(sysFsPath, "uuid")),
}
Expand Down Expand Up @@ -385,6 +385,16 @@ func readNVMeFirmwareRevision(sysFsPath string) string {
return readSysFsFile(filepath.Join(sysFsPath, "device", "firmware_rev"))
}

// readBlockDeviceModalias returns the modalias of the block device, falling
// back to the underlying PCI device's modalias when /device/modalias is absent.
func readBlockDeviceModalias(sysFsPath string) string {
if m := readSysFsFile(filepath.Join(sysFsPath, "device", "modalias")); m != "" {
return m
}

return readSysFsFile(filepath.Join(sysFsPath, "device", "device", "modalias"))
}

func (d *Device) getTransport(sysFsPath, deviceName string) string {
switch {
case strings.HasPrefix(deviceName, "nvme"):
Expand Down
45 changes: 45 additions & 0 deletions block/device_linux_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,48 @@ func TestReadNVMeFirmwareRevision(t *testing.T) {
assert.Empty(t, readNVMeFirmwareRevision(t.TempDir()))
})
}

func TestReadBlockDeviceModalias(t *testing.T) {
t.Parallel()

t.Run("scsi-style present at device/modalias", func(t *testing.T) {
t.Parallel()

root := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(root, "device"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(root, "device", "modalias"), []byte("scsi:t-0x00\n"), 0o644))

assert.Equal(t, "scsi:t-0x00", readBlockDeviceModalias(root))
})

t.Run("nvme-style present only at device/device/modalias", func(t *testing.T) {
t.Parallel()

root := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(root, "device", "device"), 0o755))
require.NoError(t, os.WriteFile(
filepath.Join(root, "device", "device", "modalias"),
[]byte("pci:v000015B7d00005030sv000015B7sd00005030bc01sc08i02\n"),
0o644,
))

assert.Equal(t, "pci:v000015B7d00005030sv000015B7sd00005030bc01sc08i02", readBlockDeviceModalias(root))
})

t.Run("device/modalias takes precedence", func(t *testing.T) {
t.Parallel()

root := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(root, "device", "device"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(root, "device", "modalias"), []byte("primary\n"), 0o644))
require.NoError(t, os.WriteFile(filepath.Join(root, "device", "device", "modalias"), []byte("fallback\n"), 0o644))

assert.Equal(t, "primary", readBlockDeviceModalias(root))
})

t.Run("missing", func(t *testing.T) {
t.Parallel()

assert.Empty(t, readBlockDeviceModalias(t.TempDir()))
})
}