@@ -10,6 +10,7 @@ import (
1010 "time"
1111
1212 "github.com/siderolabs/go-blockdevice/v2/block"
13+ "github.com/siderolabs/go-blockdevice/v2/partitioning/gpt"
1314
1415 blockres "github.com/siderolabs/talos/pkg/machinery/resources/block"
1516)
@@ -19,6 +20,8 @@ type VolumeWipeTarget struct {
1920 label string
2021
2122 parentDevName , devName string
23+
24+ partitionIndex int // partitionIndex is 1-based, but decrement before using
2225}
2326
2427// VolumeWipeTargetFromVolumeStatus creates a new VolumeWipeTarget from a VolumeStatus.
@@ -30,9 +33,10 @@ func VolumeWipeTargetFromVolumeStatus(vs *blockres.VolumeStatus) *VolumeWipeTarg
3033 }
3134
3235 return & VolumeWipeTarget {
33- label : vs .Metadata ().ID (),
34- parentDevName : parentDevName ,
35- devName : vs .TypedSpec ().Location ,
36+ label : vs .Metadata ().ID (),
37+ parentDevName : parentDevName ,
38+ devName : vs .TypedSpec ().Location ,
39+ partitionIndex : vs .TypedSpec ().PartitionIndex ,
3640 }
3741}
3842
@@ -45,9 +49,10 @@ func VolumeWipeTargetFromDiscoveredVolume(dv *blockres.DiscoveredVolume) *Volume
4549 }
4650
4751 return & VolumeWipeTarget {
48- label : dv .TypedSpec ().PartitionLabel ,
49- parentDevName : parentDevName ,
50- devName : dv .TypedSpec ().DevPath ,
52+ label : dv .TypedSpec ().PartitionLabel ,
53+ parentDevName : parentDevName ,
54+ devName : dv .TypedSpec ().DevPath ,
55+ partitionIndex : int (dv .TypedSpec ().PartitionIndex ),
5156 }
5257}
5358
@@ -62,8 +67,9 @@ func (v *VolumeWipeTarget) String() string {
6267}
6368
6469// Wipe implements runtime.PartitionTarget.
70+ // Asides from wiping the device, Wipe() also drops the partition.
6571func (v * VolumeWipeTarget ) Wipe (ctx context.Context , log func (string , ... any )) error {
66- parentBd , err := block .NewFromPath (v .parentDevName )
72+ parentBd , err := block .NewFromPath (v .parentDevName , block . OpenForWrite () )
6773 if err != nil {
6874 return fmt .Errorf ("error opening block device %q: %w" , v .parentDevName , err )
6975 }
@@ -76,14 +82,54 @@ func (v *VolumeWipeTarget) Wipe(ctx context.Context, log func(string, ...any)) e
7682
7783 defer parentBd .Unlock () //nolint:errcheck
7884
85+ if err := v .wipeWithParentLocked (log ); err != nil {
86+ return fmt .Errorf ("error wiping device %q: %w" , v .devName , err )
87+ }
88+
89+ if parentBd == nil || v .partitionIndex == 0 {
90+ return fmt .Errorf ("missing parent block device or partition index" )
91+ }
92+
93+ if err := v .dropWithParentLocked (parentBd , log ); err != nil {
94+ return fmt .Errorf ("error dropping partition: %w" , err )
95+ }
96+
97+ return nil
98+ }
99+
100+ func (v * VolumeWipeTarget ) wipeWithParentLocked (log func (string , ... any )) error {
79101 bd , err := block .NewFromPath (v .devName , block .OpenForWrite ())
80102 if err != nil {
81103 return fmt .Errorf ("error opening block device %q: %w" , v .devName , err )
82104 }
83105
84106 defer bd .Close () //nolint:errcheck
85107
86- log ("wiping the volume %q (%s)" , v .GetLabel (), v .devName )
108+ log ("wiping volume %q (%s)" , v .GetLabel (), v .devName )
87109
88110 return bd .FastWipe ()
89111}
112+
113+ func (v * VolumeWipeTarget ) dropWithParentLocked (parentBd * block.Device , log func (string , ... any )) error {
114+ log ("dropping partition %d from device %q" , v .partitionIndex , v .parentDevName )
115+
116+ gptdev , err := gpt .DeviceFromBlockDevice (parentBd )
117+ if err != nil {
118+ return fmt .Errorf ("failed to get GPT device: %w" , err )
119+ }
120+
121+ pt , err := gpt .Read (gptdev )
122+ if err != nil {
123+ return fmt .Errorf ("failed to read GPT table: %w" , err )
124+ }
125+
126+ if err = pt .DeletePartition (v .partitionIndex - 1 ); err != nil {
127+ return fmt .Errorf ("failed to delete partition: %w" , err )
128+ }
129+
130+ if err = pt .Write (); err != nil {
131+ return fmt .Errorf ("failed to write GPT table: %w" , err )
132+ }
133+
134+ return nil
135+ }
0 commit comments