@@ -77,6 +77,7 @@ type Devices interface {
7777 ) error
7878 RemoveMultipathDeviceMappingWithRetries (ctx context.Context , devicePath string , retries uint64 ,
7979 sleep time.Duration ) error
80+ ClearFormatting (ctx context.Context , devicePath string ) error
8081}
8182
8283type SizeGetter interface {
@@ -852,6 +853,57 @@ func (c *Client) ScanTargetLUN(ctx context.Context, deviceAddresses []models.Scs
852853 return nil
853854}
854855
856+ // ClearFormatting clears any formatting on the device. Use with caution.
857+ // This is a destructive operation and should only be used when you are sure you want to clear the device.
858+ // The original purpose for this was to clear incomplete LUKS formatting where the inital format errored or timed out.
859+ // This allows us to retry the LUKS format. If we don't clear the formatting, we encounter an issue where we think
860+ // the device is already formatted and don't attempt to format it again.
861+ func (c * Client ) ClearFormatting (ctx context.Context , devicePath string ) error {
862+ err := c .wipeFs (ctx , devicePath )
863+ if err != nil {
864+ // Log happens in wipeFs()
865+ return err
866+ }
867+ err = c .zeroDeviceHeader (ctx , devicePath )
868+ if err != nil {
869+ // Log happens in zeroDeviceHeader()
870+ return err
871+ }
872+ return nil
873+ }
874+
875+ // zeroDeviceHeader zeros the first 4 KiB of the device header.
876+ func (c * Client ) zeroDeviceHeader (ctx context.Context , devicePath string ) error {
877+ Logc (ctx ).WithField ("device" , devicePath ).Debug (">>>> devices.zeroDeviceHeader" )
878+ defer Logc (ctx ).Debug ("<<<< devices.zeroDeviceHeader" )
879+
880+ const zeroDeviceTimeout = 5 * time .Second
881+ args := []string {"if=/dev/zero" , "of=" + devicePath , "bs=4096" , "count=512" , "status=none" }
882+ out , err := c .command .ExecuteWithTimeout (ctx , "dd" , zeroDeviceTimeout , false , args ... )
883+ if err != nil {
884+ Logc (ctx ).WithFields (LogFields {"error" : err , "output" : string (out ), "device" : devicePath }).
885+ Error ("Failed to zero the device." )
886+ return fmt .Errorf ("failed to zero the device %v; %v" , devicePath , string (out ))
887+ }
888+
889+ return nil
890+ }
891+
892+ // wipeFs wipes the filesystem signature from the device. This is a destructive action.
893+ func (c * Client ) wipeFs (ctx context.Context , devicePath string ) error {
894+ Logc (ctx ).WithField ("device" , devicePath ).Debug (">>>> devices.wipeFs" )
895+ defer Logc (ctx ).Debug ("<<<< devices.wipeFs" )
896+
897+ const wipeFsTimeout = 10 * time .Second
898+ out , err := c .command .ExecuteWithTimeout (ctx , "wipefs" , wipeFsTimeout , false , "-a" , devicePath )
899+ if err != nil {
900+ Logc (ctx ).WithFields (LogFields {"error" : err , "output" : string (out ), "device" : devicePath }).
901+ Error ("Failed to wipe the filesystem signature." )
902+ return fmt .Errorf ("failed to wipe FS %v: %v" , devicePath , string (out ))
903+ }
904+ return nil
905+ }
906+
855907// convertToDeviceAddressValue converts the device address value to string.
856908func convertToDeviceAddressValue (value int ) string {
857909 if value < 0 {
0 commit comments