Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add device-mapper-specific block device properties #412

Merged
merged 8 commits into from Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 67 additions & 1 deletion blockdevice/stats.go
Expand Up @@ -16,13 +16,13 @@ package blockdevice
import (
"bufio"
"fmt"
"github.com/prometheus/procfs/internal/util"
"io"
"io/ioutil"
"os"
"strings"

"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 @@ -178,12 +178,37 @@ type BlockQueueStats struct {
WriteZeroesMaxBytes uint64
}

// DeviceMapperInfo models the devicemapper files that are located in the sysfs tree for each block device
// and described in the kernel documentation:
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
type DeviceMapperInfo struct {
// Name is the string containing mapped device name.
Name string
// RqBasedSeqIOMergeDeadline determines how long (in microseconds) a request that is a reasonable merge
// candidate can be queued on the request queue.
RqBasedSeqIOMergeDeadline uint64
// Suspended indicates if the device is suspended (1 is on, 0 is off).
Suspended uint64
// UseBlkMQ indicates if the device is using the request-based blk-mq I/O path mode (1 is on, 0 is off).
UseBlkMQ uint64
// UUID is the DM-UUID string or empty string if DM-UUID is not set.
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 @@ -398,3 +423,44 @@ func (fs FS) SysBlockDeviceQueueStats(device string) (BlockQueueStats, error) {
}
return stat, nil
}

func (fs FS) SysBlockDeviceMapperInfo(device string) (DeviceMapperInfo, error) {
info := DeviceMapperInfo{}
// files with uint64 fields
ventifus marked this conversation as resolved.
Show resolved Hide resolved
for file, p := range map[string]*uint64{
"rq_based_seq_io_merge_deadline": &info.RqBasedSeqIOMergeDeadline,
"suspended": &info.Suspended,
"use_blk_mq": &info.UseBlkMQ,
} {
val, err := util.ReadUintFromFile(fs.sys.Path(sysBlockPath, device, sysBlockDM, file))
if err != nil {
return DeviceMapperInfo{}, err
}
*p = val
}
// files with string fields
ventifus marked this conversation as resolved.
Show resolved Hide resolved
for file, p := range map[string]*string{
"name": &info.Name,
"uuid": &info.UUID,
} {
val, err := util.SysReadFile(fs.sys.Path(sysBlockPath, device, sysBlockDM, file))
if err != nil {
return DeviceMapperInfo{}, err
}
*p = val
}
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

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

import (
"os"
"reflect"
"testing"
)
Expand Down Expand Up @@ -152,3 +153,69 @@ func TestBlockDevice(t *testing.T) {
t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", blockQueueStatExpected, blockQueueStat)
}
}

func TestBlockDmInfo(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)
}
dm0Info, err := blockdevice.SysBlockDeviceMapperInfo(devices[0])
if err != nil {
t.Fatal(err)
}

dm0InfoExpected := DeviceMapperInfo{
Name: "vg0--lv_root",
RqBasedSeqIOMergeDeadline: 0,
Suspended: 0,
UseBlkMQ: 0,
UUID: "LVM-3zSHSR5Nbf4j7g6auAAefWY2CMaX01theZYEvQyecVsm2WtX3iY5q51qq5dWWOq7",
}
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)
}
}
65 changes: 65 additions & 0 deletions fixtures.ttar
Expand Up @@ -3231,6 +3231,41 @@ Mode: 775
Directory: fixtures/sys/block/dm-0
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/block/dm-0/dm
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/block/dm-0/dm/name
Lines: 1
vg0--lv_rootEOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/block/dm-0/dm/rq_based_seq_io_merge_deadline
Lines: 1
0EOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/block/dm-0/dm/suspended
Lines: 1
0EOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/block/dm-0/dm/use_blk_mq
Lines: 1
0EOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/block/dm-0/dm/uuid
Lines: 1
LVM-3zSHSR5Nbf4j7g6auAAefWY2CMaX01theZYEvQyecVsm2WtX3iY5q51qq5dWWOq7EOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/block/dm-0/slaves
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/block/dm-0/slaves/sda
Lines: 0
Mode: 664
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/block/dm-0/stat
Lines: 1
6447303 0 710266738 1529043 953216 0 31201176 4557464 0 796160 6088971
Expand Down Expand Up @@ -3478,6 +3513,27 @@ Mode: 664
Directory: fixtures/sys/class
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/class/block
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/block/dm-0
SymlinkTo: ../../devices/virtual/block/dm-0
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/block/dm-1
SymlinkTo: ../../devices/virtual/block/dm-1
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/block/dm-2
SymlinkTo: ../../devices/virtual/block/dm-2
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/block/dm-3
SymlinkTo: ../../devices/virtual/block/dm-3
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/block/dm-4
SymlinkTo: ../../devices/virtual/block/dm-4
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/class/block/dm-5
SymlinkTo: ../../devices/virtual/block/dm-5
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/class/dmi
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down Expand Up @@ -6491,6 +6547,15 @@ nr_zone_active_file 11
nr_zone_unevictable 12
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/virtual
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/virtual/block
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/devices/virtual/block/dm-0
Mode: 775
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Directory: fixtures/sys/fs
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down