mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-29 07:21:11 +01:00
chore: use go-blockdevice for zeroing partitions
Use the `go-blockdevice` library to zero partitions. Also added a test that writes `ones` to the partition and verifies its zeroes after zeroing it. Signed-off-by: Noel Georgi <git@frezbo.dev>
This commit is contained in:
parent
e6dde8ffc5
commit
e912c0dfcf
@ -7,9 +7,7 @@ package partition
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/siderolabs/go-blockdevice/blockdevice"
|
"github.com/siderolabs/go-blockdevice/blockdevice"
|
||||||
|
|
||||||
@ -39,7 +37,7 @@ func NewFormatOptions(label string) *FormatOptions {
|
|||||||
// Format zeroes the device and formats it using filesystem type provided.
|
// Format zeroes the device and formats it using filesystem type provided.
|
||||||
func Format(devname string, t *FormatOptions) error {
|
func Format(devname string, t *FormatOptions) error {
|
||||||
if t.FileSystemType == FilesystemTypeNone {
|
if t.FileSystemType == FilesystemTypeNone {
|
||||||
return zeroPartition(devname, int64(t.Size))
|
return zeroPartition(devname)
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := []makefs.Option{makefs.WithForce(t.Force), makefs.WithLabel(t.Label)}
|
opts := []makefs.Option{makefs.WithForce(t.Force), makefs.WithLabel(t.Label)}
|
||||||
@ -56,29 +54,17 @@ func Format(devname string, t *FormatOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// zeroPartition fills the partition with zeroes.
|
// zeroPartition fills the partition with zeroes.
|
||||||
func zeroPartition(devname string, size int64) (err error) {
|
func zeroPartition(devname string) (err error) {
|
||||||
log.Printf("zeroing out %q", devname)
|
log.Printf("zeroing out %q", devname)
|
||||||
|
|
||||||
zeroes, err := os.Open("/dev/zero")
|
part, err := blockdevice.Open(devname, blockdevice.WithExclusiveLock(true))
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer zeroes.Close() //nolint:errcheck
|
|
||||||
|
|
||||||
part, err := os.OpenFile(devname, os.O_WRONLY, 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer part.Close() //nolint:errcheck
|
defer part.Close() //nolint:errcheck
|
||||||
|
|
||||||
// wipe at least minimal header size
|
_, err = part.Wipe()
|
||||||
if size == 0 {
|
|
||||||
size = blockdevice.FastWipeRange
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.CopyN(part, zeroes, size)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
157
internal/pkg/partition/format_test.go
Normal file
157
internal/pkg/partition/format_test.go
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// 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 partition provides common utils for system partition format.
|
||||||
|
package partition_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/siderolabs/go-blockdevice/blockdevice"
|
||||||
|
"github.com/siderolabs/go-blockdevice/blockdevice/loopback"
|
||||||
|
"github.com/siderolabs/go-blockdevice/blockdevice/partition/gpt"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/siderolabs/talos/internal/pkg/partition"
|
||||||
|
)
|
||||||
|
|
||||||
|
type manifestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
disk *os.File
|
||||||
|
loopbackDevice *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
diskSize = 10 * 1024 * 1024 // 10 MiB
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestManifestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(manifestSuite))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *manifestSuite) SetupTest() {
|
||||||
|
suite.skipIfNotRoot()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
suite.disk, err = os.CreateTemp("", "talos")
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Require().NoError(suite.disk.Truncate(diskSize))
|
||||||
|
|
||||||
|
suite.loopbackDevice, err = loopback.NextLoopDevice()
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.T().Logf("Using %s", suite.loopbackDevice.Name())
|
||||||
|
|
||||||
|
suite.Require().NoError(loopback.Loop(suite.loopbackDevice, suite.disk))
|
||||||
|
|
||||||
|
suite.Require().NoError(loopback.LoopSetReadWrite(suite.loopbackDevice))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *manifestSuite) TearDownTest() {
|
||||||
|
if suite.loopbackDevice != nil {
|
||||||
|
suite.Assert().NoError(loopback.Unloop(suite.loopbackDevice))
|
||||||
|
}
|
||||||
|
|
||||||
|
if suite.disk != nil {
|
||||||
|
suite.Assert().NoError(os.Remove(suite.disk.Name()))
|
||||||
|
suite.Assert().NoError(suite.disk.Close())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *manifestSuite) skipIfNotRoot() {
|
||||||
|
if os.Getuid() != 0 {
|
||||||
|
suite.T().Skip("can't run the test as non-root")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *manifestSuite) skipUnderBuildkit() {
|
||||||
|
hostname, _ := os.Hostname() //nolint:errcheck
|
||||||
|
|
||||||
|
if hostname == "buildkitsandbox" {
|
||||||
|
suite.T().Skip("test not supported under buildkit as partition devices are not propagated from /dev")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *manifestSuite) TestZeroPartition() {
|
||||||
|
suite.skipUnderBuildkit()
|
||||||
|
|
||||||
|
bd, err := blockdevice.Open(suite.loopbackDevice.Name(), blockdevice.WithExclusiveLock(true))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
defer bd.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
pt, err := gpt.New(bd.Device(), gpt.WithMarkMBRBootable(false))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// Create a partition table with a single partition.
|
||||||
|
_, err = pt.Add(0, gpt.WithMaximumSize(true), gpt.WithPartitionName("zerofill"))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Require().NoError(pt.Write())
|
||||||
|
suite.Require().NoError(bd.Close())
|
||||||
|
|
||||||
|
bd, err = blockdevice.Open(suite.loopbackDevice.Name(), blockdevice.WithExclusiveLock(true))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
defer bd.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
fills := bytes.NewBuffer(bytes.Repeat([]byte{1}, 10))
|
||||||
|
|
||||||
|
parts, err := bd.GetPartition("zerofill")
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
part, err := parts.Path()
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// open the partition as read write
|
||||||
|
dst, err := os.OpenFile(part, os.O_WRONLY, 0o644)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
defer dst.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
// Write some data to the partition.
|
||||||
|
_, err = io.Copy(dst, fills)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
data, err := os.Open(part)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
defer data.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
read := make([]byte, fills.Len())
|
||||||
|
|
||||||
|
_, err = data.Read(read)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().NoError(data.Close())
|
||||||
|
|
||||||
|
suite.Assert().True(bytes.Equal(fills.Bytes(), read))
|
||||||
|
|
||||||
|
suite.Require().NoError(bd.Close())
|
||||||
|
|
||||||
|
err = partition.Format(part, &partition.FormatOptions{
|
||||||
|
FileSystemType: partition.FilesystemTypeNone,
|
||||||
|
})
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// reading 10 times more than what we wrote should still return 0 since the partition is wiped
|
||||||
|
zerofills := bytes.NewBuffer(bytes.Repeat([]byte{0}, 100))
|
||||||
|
|
||||||
|
data, err = os.Open(part)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
defer data.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
read = make([]byte, zerofills.Len())
|
||||||
|
|
||||||
|
_, err = data.Read(read)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
suite.Assert().True(bytes.Equal(zerofills.Bytes(), read))
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user