Skip to content

Commit f6d6306

Browse files
committed
fix: wipe system partitions correctly via kernel args
Use `DiscoveredVolumes` instead of `VolumeStatus`, force reboot to avoid confusion in the volume controller. Fixes #9448 Signed-off-by: Andrey Smirnov <[email protected]> (cherry picked from commit 519a483)
1 parent 4d279c6 commit f6d6306

File tree

3 files changed

+81
-38
lines changed

3 files changed

+81
-38
lines changed

internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,11 @@ func (opt *ResetOptions) GetSystemDiskTargets() []runtime.PartitionTarget {
569569
return xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) runtime.PartitionTarget { return t })
570570
}
571571

572+
// String implements runtime.ResetOptions interface.
573+
func (opt *ResetOptions) String() string {
574+
return strings.Join(xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) string { return t.String() }), ", ")
575+
}
576+
572577
// Reset resets the node.
573578
//
574579
//nolint:gocyclo
@@ -635,9 +640,7 @@ func (s *Server) Reset(ctx context.Context, in *machine.ResetRequest) (reply *ma
635640
return nil, fmt.Errorf("failed to reset: volume %q is not ready", spec.Label)
636641
}
637642

638-
target := &partition.VolumeWipeTarget{
639-
VolumeStatus: volumeStatus,
640-
}
643+
target := partition.VolumeWipeTargetFromVolumeStatus(volumeStatus)
641644

642645
if spec.Wipe {
643646
opts.systemDiskTargets = append(opts.systemDiskTargets, target)

internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go

+30-21
Original file line numberDiff line numberDiff line change
@@ -1583,15 +1583,7 @@ func ResetSystemDiskPartitions(seq runtime.Sequence, _ any) (runtime.TaskExecuti
15831583

15841584
logger.Printf("finished resetting system disks %s", diskTargets)
15851585

1586-
bootWiped := slices.ContainsFunc(diskTargets, func(t runtime.PartitionTarget) bool {
1587-
return t.GetLabel() == constants.BootPartitionLabel
1588-
})
1589-
1590-
if bootWiped {
1591-
return reboot(ctx, logger, r) // only reboot when we wiped boot partition
1592-
}
1593-
1594-
return nil
1586+
return reboot(ctx, logger, r)
15951587
}, "wipeSystemDiskPartitions"
15961588
}
15971589

@@ -1710,29 +1702,45 @@ func (opt targets) GetSystemDiskTargets() []runtime.PartitionTarget {
17101702
return xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) runtime.PartitionTarget { return t })
17111703
}
17121704

1713-
func parseTargets(ctx context.Context, r runtime.Runtime, wipeStr string) (targets, error) {
1705+
func (opt targets) String() string {
1706+
return strings.Join(xslices.Map(opt.systemDiskTargets, func(t *partition.VolumeWipeTarget) string { return t.String() }), ", ")
1707+
}
1708+
1709+
func parseTargets(ctx context.Context, r runtime.Runtime, wipeStr string) (SystemDiskTargets, error) {
17141710
after, found := strings.CutPrefix(wipeStr, "system:")
17151711
if !found {
17161712
return targets{}, fmt.Errorf("invalid wipe labels string: %q", wipeStr)
17171713
}
17181714

1719-
var result []*partition.VolumeWipeTarget //nolint:prealloc
1715+
var result []*partition.VolumeWipeTarget
1716+
1717+
// in this early phase, we don't have VolumeStatus resources, so instead we'd use DiscoveredVolumes
1718+
// to get the volume paths
1719+
discoveredVolumes, err := safe.StateListAll[*blockres.DiscoveredVolume](ctx, r.State().V1Alpha2().Resources())
1720+
if err != nil {
1721+
return targets{}, err
1722+
}
17201723

17211724
for _, label := range strings.Split(after, ",") {
1722-
volumeStatus, err := safe.ReaderGetByID[*blockres.VolumeStatus](ctx, r.State().V1Alpha2().Resources(), label)
1723-
if err != nil {
1724-
return targets{}, fmt.Errorf("failed to get volume status with label %q: %w", label, err)
1725-
}
1725+
found := false
17261726

1727-
if volumeStatus.TypedSpec().Phase != blockres.VolumePhaseReady {
1728-
return targets{}, fmt.Errorf("failed to reset: volume %q is not ready", label)
1729-
}
1727+
for iter := discoveredVolumes.Iterator(); iter.Next(); {
1728+
discoveredVolume := iter.Value()
1729+
1730+
if discoveredVolume.TypedSpec().PartitionLabel != label {
1731+
continue
1732+
}
1733+
1734+
result = append(result, partition.VolumeWipeTargetFromDiscoveredVolume(discoveredVolume))
1735+
1736+
found = true
17301737

1731-
target := &partition.VolumeWipeTarget{
1732-
VolumeStatus: volumeStatus,
1738+
break
17331739
}
17341740

1735-
result = append(result, target)
1741+
if !found {
1742+
return targets{}, fmt.Errorf("failed to get volume status with label %q", label)
1743+
}
17361744
}
17371745

17381746
if len(result) == 0 {
@@ -1746,6 +1754,7 @@ func parseTargets(ctx context.Context, r runtime.Runtime, wipeStr string) (targe
17461754
// It's a subset of [runtime.ResetOptions].
17471755
type SystemDiskTargets interface {
17481756
GetSystemDiskTargets() []runtime.PartitionTarget
1757+
fmt.Stringer
17491758
}
17501759

17511760
// ResetSystemDiskSpec represents the task to reset the system disk by spec.

internal/pkg/partition/wipe.go

+45-14
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,74 @@ import (
1616

1717
// VolumeWipeTarget is a target for wiping a volume.
1818
type VolumeWipeTarget struct {
19-
VolumeStatus *blockres.VolumeStatus
19+
label string
20+
21+
parentDevName, devName string
2022
}
2123

22-
// GetLabel implements runtime.PartitionTarget.
23-
func (v *VolumeWipeTarget) GetLabel() string {
24-
return v.VolumeStatus.Metadata().ID()
24+
// VolumeWipeTargetFromVolumeStatus creates a new VolumeWipeTarget from a VolumeStatus.
25+
func VolumeWipeTargetFromVolumeStatus(vs *blockres.VolumeStatus) *VolumeWipeTarget {
26+
parentDevName := vs.TypedSpec().ParentLocation
27+
28+
if parentDevName == "" {
29+
parentDevName = vs.TypedSpec().Location
30+
}
31+
32+
return &VolumeWipeTarget{
33+
label: vs.Metadata().ID(),
34+
parentDevName: parentDevName,
35+
devName: vs.TypedSpec().Location,
36+
}
2537
}
2638

27-
// Wipe implements runtime.PartitionTarget.
28-
func (v *VolumeWipeTarget) Wipe(ctx context.Context, log func(string, ...any)) error {
29-
parentDevName := v.VolumeStatus.TypedSpec().ParentLocation
39+
// VolumeWipeTargetFromDiscoveredVolume creates a new VolumeWipeTarget from a DiscoveredVolume.
40+
func VolumeWipeTargetFromDiscoveredVolume(dv *blockres.DiscoveredVolume) *VolumeWipeTarget {
41+
parentDevName := dv.TypedSpec().ParentDevPath
3042

3143
if parentDevName == "" {
32-
parentDevName = v.VolumeStatus.TypedSpec().Location
44+
parentDevName = dv.TypedSpec().DevPath
3345
}
3446

35-
parentBd, err := block.NewFromPath(parentDevName)
47+
return &VolumeWipeTarget{
48+
label: dv.TypedSpec().PartitionLabel,
49+
parentDevName: parentDevName,
50+
devName: dv.TypedSpec().DevPath,
51+
}
52+
}
53+
54+
// GetLabel implements runtime.PartitionTarget.
55+
func (v *VolumeWipeTarget) GetLabel() string {
56+
return v.label
57+
}
58+
59+
// String implements runtime.PartitionTarget.
60+
func (v *VolumeWipeTarget) String() string {
61+
return fmt.Sprintf("%s:%s", v.label, v.devName)
62+
}
63+
64+
// Wipe implements runtime.PartitionTarget.
65+
func (v *VolumeWipeTarget) Wipe(ctx context.Context, log func(string, ...any)) error {
66+
parentBd, err := block.NewFromPath(v.parentDevName)
3667
if err != nil {
37-
return fmt.Errorf("error opening block device %q: %w", parentDevName, err)
68+
return fmt.Errorf("error opening block device %q: %w", v.parentDevName, err)
3869
}
3970

4071
defer parentBd.Close() //nolint:errcheck
4172

4273
if err = parentBd.RetryLockWithTimeout(ctx, true, time.Minute); err != nil {
43-
return fmt.Errorf("error locking block device %q: %w", parentDevName, err)
74+
return fmt.Errorf("error locking block device %q: %w", v.parentDevName, err)
4475
}
4576

4677
defer parentBd.Unlock() //nolint:errcheck
4778

48-
bd, err := block.NewFromPath(v.VolumeStatus.TypedSpec().Location, block.OpenForWrite())
79+
bd, err := block.NewFromPath(v.devName, block.OpenForWrite())
4980
if err != nil {
50-
return fmt.Errorf("error opening block device %q: %w", v.VolumeStatus.TypedSpec().Location, err)
81+
return fmt.Errorf("error opening block device %q: %w", v.devName, err)
5182
}
5283

5384
defer bd.Close() //nolint:errcheck
5485

55-
log("wiping the volume %q (%s)", v.GetLabel(), v.VolumeStatus.TypedSpec().Location)
86+
log("wiping the volume %q (%s)", v.GetLabel(), v.devName)
5687

5788
return bd.FastWipe()
5889
}

0 commit comments

Comments
 (0)