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

WIP: Add swap/mdadm block device detection #76

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
4 changes: 4 additions & 0 deletions blockdevice/filesystem/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import (
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/ext4"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/iso9660"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/luks"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/mdraid"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/msdos"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/swap"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/vfat"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/xfs"
)
Expand Down Expand Up @@ -69,6 +71,8 @@ func Probe(path string) (SuperBlocker, error) { //nolint:ireturn
&xfs.SuperBlock{},
&luks.SuperBlock{},
&ext4.SuperBlock{},
&swap.SuperBlock{},
&mdraid.SuperBlock{},
}

for _, sb := range superblocks {
Expand Down
6 changes: 6 additions & 0 deletions blockdevice/filesystem/mdraid/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package mdraid provides functions for working with the softraid.
package mdraid
55 changes: 55 additions & 0 deletions blockdevice/filesystem/mdraid/superblock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package mdraid

import (
"encoding/binary"
)

const (
// Magic is the mdraid magic signature.
Magic = 0xa92b4efc
)

// SuperBlock represents the swap super block.
// https://raid.wiki.kernel.org/index.php/RAID_superblock_formats
type SuperBlock struct {
Magic [4]uint8
Version [4]uint8
Feature uint32
_ uint32
UUID [16]uint8
Name [32]uint8
CTime [2]uint32
Level uint32
}

// Is implements the SuperBlocker interface.
func (sb *SuperBlock) Is() bool {
// if binary.LittleEndian.Uint32(sb.Magic[:]) == Magic {
// log.Printf("Data: %+v", sb)
// log.Printf("Version: %d", binary.LittleEndian.Uint32(sb.Version[:]))
// log.Printf("Name: %s", bytes.Trim(sb.Name[:], "\x00"))
// uid, _ := uuid.FromBytes(sb.UUID[:])
// log.Printf("UUID: %s", uid.String())
// }

return binary.LittleEndian.Uint32(sb.Version[:]) == 1 && binary.LittleEndian.Uint32(sb.Magic[:]) == Magic
}

// Offset implements the SuperBlocker interface.
func (sb *SuperBlock) Offset() int64 {
return 0x1000
}

// Type implements the SuperBlocker interface.
func (sb *SuperBlock) Type() string {
return "mdraid"
}

// Encrypted implements the SuperBlocker interface.
func (sb *SuperBlock) Encrypted() bool {
return false
}
6 changes: 6 additions & 0 deletions blockdevice/filesystem/swap/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package swap provides functions for working with the swap.
package swap
52 changes: 52 additions & 0 deletions blockdevice/filesystem/swap/superblock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package swap

import (
"encoding/binary"
"syscall"
)

const (
// Magic is the swap magic signature.
Magic = "SWAPSPACE2"
magicSize = len(Magic)
)

// SuperBlock represents the swap super block.
type SuperBlock struct {
Varsion uint32
LastPage uint32
NrBadPages uint32
UUID [0x10]uint8 // 1036
Label [0x10]uint8 // 1052
Padding [0x75]uint32
BadPages [1]uint32
}

// Is implements the SuperBlocker interface.
func (sb *SuperBlock) Is() bool {
return sb.Varsion == binary.BigEndian.Uint32([]byte{1, 0, 0, 0})
}

// Offset implements the SuperBlocker interface.
func (sb *SuperBlock) Offset() int64 {
return 0x400
}

// OffsetMagic implements the SuperBlocker interface.
func (sb *SuperBlock) OffsetMagic() int64 {
return int64(syscall.Getpagesize()) - int64(magicSize)
}

// Type implements the SuperBlocker interface.
func (sb *SuperBlock) Type() string {
return "swap"
}

// Encrypted implements the SuperBlocker interface.
func (sb *SuperBlock) Encrypted() bool {
return false
}
15 changes: 15 additions & 0 deletions blockdevice/probe/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/siderolabs/go-blockdevice/blockdevice"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/ext4"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/iso9660"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/mdraid"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/msdos"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/swap"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/vfat"
"github.com/siderolabs/go-blockdevice/blockdevice/filesystem/xfs"
"github.com/siderolabs/go-blockdevice/blockdevice/partition/gpt"
Expand Down Expand Up @@ -79,6 +82,18 @@ func WithFileSystemLabel(label string) SelectOption {
if bytes.Equal(trimmed, []byte(label)) {
return true, nil
}
case *swap.SuperBlock:
trimmed := bytes.TrimRight(sb.Label[:], "\x00")
if bytes.Equal(trimmed, []byte(label)) {
return true, nil
}
case *mdraid.SuperBlock:
trimmed := bytes.Trim(sb.Name[:], "\x00")
mdlabel := strings.Split(string(trimmed), ":")

if len(mdlabel) == 2 && mdlabel[1] == label {
return true, nil
}
}
}

Expand Down
34 changes: 34 additions & 0 deletions blockdevice/probe/probe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ func (suite *ProbeSuite) setSystemLabelEXT4(name string) {
suite.Require().NoError(cmd.Run())
}

func (suite *ProbeSuite) setSystemLabelSwap(name string) {
cmd := exec.Command("mkswap", "-L", name, suite.LoopbackDevice.Name())
suite.Require().NoError(cmd.Run())
}

func (suite *ProbeSuite) TestBlockDeviceWithSymlinkResolves() {
// Create a symlink to the block device
symlink := suite.Dev.Name() + ".link"
Expand Down Expand Up @@ -169,6 +174,35 @@ func (suite *ProbeSuite) TestProbeByFilesystemLabelBlockdeviceEXT4() {
suite.Require().Equal(suite.LoopbackDevice.Name(), probed[0].Path)
}

func (suite *ProbeSuite) TestProbeByFilesystemLabelBlockdeviceSWAP() {
suite.setSystemLabelSwap("SWAPBD")

probed, err := probe.All(probe.WithFileSystemLabel("SWAPBD"))
suite.Require().NoError(err)
suite.Require().Equal(1, len(probed))

suite.Require().Equal(suite.LoopbackDevice.Name(), probed[0].Device().Name())
suite.Require().Equal(suite.LoopbackDevice.Name(), probed[0].Path)
}

func (suite *ProbeSuite) TestProbeMDRaid() {
name := "TESTRAID"
cmd := exec.Command("mdadm", "--create", "/dev/md1", "-N", name, "--metadata=1.2", "--level=1", "--raid-devices=2", "missing", suite.LoopbackDevice.Name())
suite.Require().NoError(cmd.Run())

defer func() {
cmd := exec.Command("mdadm", "--stop", "/dev/md1")
cmd.Run()
}()

probed, err := probe.All(probe.WithFileSystemLabel(name))
suite.Require().NoError(err)
suite.Require().Equal(1, len(probed))

suite.Require().Equal(suite.LoopbackDevice.Name(), probed[0].Device().Name())
suite.Require().Equal(suite.LoopbackDevice.Name(), probed[0].Path)
}

func (suite *ProbeSuite) TestProbeByFilesystemLabelPartition() {
suite.addPartition("FOO", 1024*1024*256, 16)
suite.addPartition("FSLABELPART", 1024*1024*2, 12)
Expand Down