Skip to content

Commit

Permalink
Properly detect dm devices
Browse files Browse the repository at this point in the history
Fixes: jaypipes#298
Signed-off-by: Avishay Traeger <[email protected]>
  • Loading branch information
avishayt committed Mar 15, 2022
1 parent 4d0ed8f commit 3414e78
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
4 changes: 4 additions & 0 deletions pkg/block/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
DRIVE_TYPE_FDD // Floppy disk drive
DRIVE_TYPE_ODD // Optical disk drive
DRIVE_TYPE_SSD // Solid-state drive
DRIVE_TYPE_MAPPER // Mapper device
)

var (
Expand All @@ -38,6 +39,7 @@ var (
DRIVE_TYPE_FDD: "FDD",
DRIVE_TYPE_ODD: "ODD",
DRIVE_TYPE_SSD: "SSD",
DRIVE_TYPE_MAPPER: "Mapper",
}

// NOTE(fromani): the keys are all lowercase and do not match
Expand All @@ -51,6 +53,7 @@ var (
"fdd": DRIVE_TYPE_FDD,
"odd": DRIVE_TYPE_ODD,
"ssd": DRIVE_TYPE_SSD,
"mapper": DRIVE_TYPE_MAPPER,
}
)

Expand Down Expand Up @@ -163,6 +166,7 @@ type Disk struct {
SerialNumber string `json:"serial_number"`
WWN string `json:"wwn"`
Partitions []*Partition `json:"partitions"`
Members []string `json:"members"`
// TODO(jaypipes): Add PCI field for accessing PCI device information
// PCI *PCIDevice `json:"pci"`
}
Expand Down
19 changes: 18 additions & 1 deletion pkg/block/block_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,19 @@ func diskIsRemovable(paths *linuxpath.Paths, disk string) bool {
return removable == "1"
}

func diskMembers(ctx *context.Context, paths *linuxpath.Paths, disk string) []string {
out := make([]string, 0)
path := filepath.Join(paths.SysBlock, disk, "slaves")
files, err := ioutil.ReadDir(path)
if err != nil {
return out
}
for _, file := range files {
out = append(out, file.Name())
}
return out
}

func disks(ctx *context.Context, paths *linuxpath.Paths) []*Disk {
// In Linux, we could use the fdisk, lshw or blockdev commands to list disk
// information, however all of these utilities require root privileges to
Expand All @@ -271,7 +284,7 @@ func disks(ctx *context.Context, paths *linuxpath.Paths) []*Disk {
driveType, storageController := diskTypes(dname)
// TODO(jaypipes): Move this into diskTypes() once abstracting
// diskIsRotational for ease of unit testing
if !diskIsRotational(ctx, paths, dname) {
if driveType != DRIVE_TYPE_MAPPER && !diskIsRotational(ctx, paths, dname) {
driveType = DRIVE_TYPE_SSD
}
size := diskSizeBytes(paths, dname)
Expand All @@ -283,6 +296,7 @@ func disks(ctx *context.Context, paths *linuxpath.Paths) []*Disk {
serialNo := diskSerialNumber(paths, dname)
wwn := diskWWN(paths, dname)
removable := diskIsRemovable(paths, dname)
members := diskMembers(ctx, paths, dname)

d := &Disk{
Name: dname,
Expand All @@ -297,6 +311,7 @@ func disks(ctx *context.Context, paths *linuxpath.Paths) []*Disk {
Model: model,
SerialNumber: serialNo,
WWN: wwn,
Members: members,
}

parts := diskPartitions(ctx, paths, dname)
Expand Down Expand Up @@ -345,6 +360,8 @@ func diskTypes(dname string) (
} else if strings.HasPrefix(dname, "mmc") {
driveType = DRIVE_TYPE_SSD
storageController = STORAGE_CONTROLLER_MMC
} else if strings.HasPrefix(dname, "dm-") {
driveType = DRIVE_TYPE_MAPPER
}

return driveType, storageController
Expand Down
48 changes: 48 additions & 0 deletions pkg/block/block_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@
package block

import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"

"github.com/jaypipes/ghw/pkg/context"
"github.com/jaypipes/ghw/pkg/linuxpath"
)

func TestParseMountEntry(t *testing.T) {
Expand Down Expand Up @@ -179,3 +184,46 @@ func TestDiskTypes(t *testing.T) {
}
}
}

func TestMapper(t *testing.T) {
if _, ok := os.LookupEnv("GHW_TESTING_SKIP_BLOCK"); ok {
t.Skip("Skipping block tests.")
}

baseDir, _ := ioutil.TempDir("", "test")
defer os.RemoveAll(baseDir)
ctx := context.New()
ctx.Chroot = baseDir
paths := linuxpath.New(ctx)

_ = os.MkdirAll(paths.SysBlock, 0755)
_ = os.MkdirAll(paths.RunUdevData, 0755)

// Emulate a mapper device with no members
_ = os.Mkdir(filepath.Join(paths.SysBlock, "dm-0"), 0755)
_ = ioutil.WriteFile(filepath.Join(paths.SysBlock, "dm-0", "size"), []byte("419430400\n"), 0644)
_ = os.Mkdir(filepath.Join(paths.SysBlock, "dm-0", "queue"), 0755)
_ = ioutil.WriteFile(filepath.Join(paths.SysBlock, "dm-0", "queue", "rotational"), []byte("0\n"), 0644)
_ = ioutil.WriteFile(filepath.Join(paths.SysBlock, "dm-0", "queue", "physical_block_size"), []byte("512\n"), 0644)

diskInventory := disks(ctx, paths)
if diskInventory[0].DriveType != DRIVE_TYPE_MAPPER {
t.Fatalf("Got drive type %s, but expected Mapper", diskInventory[0].DriveType)
}
if len(diskInventory[0].Members) > 0 {
t.Fatalf("Got %d members but didn't expect any", len(diskInventory[0].Members))
}

// Add members (we create regular files here for brevity even though in reality they are symlinks)
_ = os.Mkdir(filepath.Join(paths.SysBlock, "dm-0", "slaves"), 0755)
_ = ioutil.WriteFile(filepath.Join(paths.SysBlock, "dm-0", "slaves", "sda"), []byte(""), 0644)
_ = ioutil.WriteFile(filepath.Join(paths.SysBlock, "dm-0", "slaves", "sdb"), []byte(""), 0644)

diskInventory = disks(ctx, paths)
if diskInventory[0].DriveType != DRIVE_TYPE_MAPPER {
t.Fatalf("Got drive type %s, but expected Mapper", diskInventory[0].DriveType)
}
if len(diskInventory[0].Members) != 2 {
t.Fatalf("Got %d members but expected 2", len(diskInventory[0].Members))
}
}

0 comments on commit 3414e78

Please sign in to comment.