Skip to content

Commit

Permalink
Enumerate block device slaves as UnderlyingDeviceInfo
Browse files Browse the repository at this point in the history
Signed-off-by: W. Andrew Denton <git@flying-snail.net>
  • Loading branch information
W. Andrew Denton committed Sep 14, 2021
1 parent fdb88ff commit 8ea1dda
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
23 changes: 21 additions & 2 deletions blockdevice/stats.go
Expand Up @@ -21,9 +21,8 @@ import (
"os"
"strings"

"github.com/prometheus/procfs/internal/util"

"github.com/prometheus/procfs/internal/fs"
"github.com/prometheus/procfs/internal/util"
)

// Info contains identifying information for a block device such as a disk drive
Expand Down Expand Up @@ -196,13 +195,20 @@ type DeviceMapperInfo struct {
Uuid string
}

// UnderlyingDevices models the list of devices that this device is built from.
type UnderlyingDeviceInfo struct {
// DeviceNames is the list of devices names
DeviceNames []string
}

const (
procDiskstatsPath = "diskstats"
procDiskstatsFormat = "%d %d %s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"
sysBlockPath = "block"
sysBlockStatFormat = "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"
sysBlockQueue = "queue"
sysBlockDm = "dm"
sysUnderlyingDev = "slaves"
)

// FS represents the pseudo-filesystems proc and sys, which provides an
Expand Down Expand Up @@ -445,3 +451,16 @@ func (fs FS) SysBlockDeviceMapperInfo(device string) (DeviceMapperInfo, error) {
}
return info, nil
}

func (fs FS) SysBlockDeviceUnderlyingDevices(device string) (UnderlyingDeviceInfo, error) {
underlyingDir, err := os.Open(fs.sys.Path(sysBlockPath, device, sysUnderlyingDev))
if err != nil {
return UnderlyingDeviceInfo{}, err
}
underlying, err := underlyingDir.Readdirnames(0)
if err != nil {
return UnderlyingDeviceInfo{}, err
}
return UnderlyingDeviceInfo{DeviceNames: underlying}, nil

}
41 changes: 41 additions & 0 deletions blockdevice/stats_test.go
Expand Up @@ -14,6 +14,7 @@
package blockdevice

import (
"os"
"reflect"
"testing"
)
Expand Down Expand Up @@ -177,4 +178,44 @@ func TestBlockDmInfo(t *testing.T) {
if !reflect.DeepEqual(dm0Info, dm0InfoExpected) {
t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", dm0InfoExpected, dm0Info)
}

dm1Info, err := blockdevice.SysBlockDeviceMapperInfo(devices[1])
if err != nil {
if _, ok := err.(*os.PathError); ok {
// Fail the test if there's an error other than PathError.
if !os.IsNotExist(err) {
t.Fatal(err)
}
} else {
t.Fatal(err)
}
} else {
t.Fatal("SysBlockDeviceMapperInfo on sda was supposed to fail.")
}
dm1InfoExpected := DeviceMapperInfo{}
if !reflect.DeepEqual(dm1Info, dm1InfoExpected) {
t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", dm0InfoExpected, dm0Info)
}
}

func TestSysBlockDeviceUnderlyingDevices(t *testing.T) {
blockdevice, err := NewFS("../fixtures/proc", "../fixtures/sys")
if err != nil {
t.Fatalf("failed to access blockdevice fs: %v", err)
}
devices, err := blockdevice.SysBlockDevices()
if err != nil {
t.Fatal(err)
}

underlying0, err := blockdevice.SysBlockDeviceUnderlyingDevices(devices[0])
if err != nil {
t.Fatal(err)
}
underlying0Expected := UnderlyingDeviceInfo{
DeviceNames: []string{"sda"},
}
if !reflect.DeepEqual(underlying0, underlying0Expected) {
t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", underlying0Expected, underlying0)
}
}

0 comments on commit 8ea1dda

Please sign in to comment.