Skip to content
Open
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
33 changes: 32 additions & 1 deletion pkg/repart/disk_repart.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ package repart
import (
_ "embed"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
Expand All @@ -45,6 +47,8 @@ const (
// Do not change these values as this could break backward compatibility on already installed systems (e.g. reseting a system)
configType = "2ecf8b13-6846-4e8a-9bc3-284ff5e2ac22"
recoveryType = "3265f37b-3105-4777-bd97-cfcd9cc7cf99"

blkdiscardNotSupported = 2 // blkdiscard exit code for devices that do not support discard requests
)

//go:embed templates/partition.conf.tpl
Expand Down Expand Up @@ -176,7 +180,34 @@ func repartDisk(s *sys.System, d *deployment.Disk, empty string) (err error) {
parts[i] = Partition{Partition: part}
}

return runSystemdRepart(s, d.Device, parts, fmt.Sprintf("--empty=%s", empty))
// systemd-repart trimming the disk could result in the entire disk waiting to be fully zero'd out. This could hang
// installs on large drives. Now, before systemd-repart is triggered, we manually discard the entire disk in one pass
// through blkdiscard. This results in a native TRIM being executed whenever the drive typically runs the TRIM engine.
if empty == "force" {
err = discardDevice(s, d.Device)
if err != nil {
return err
}
}

return runSystemdRepart(s, d.Device, parts, fmt.Sprintf("--empty=%s", empty), "--discard=no")
}

// discardDevice discards the given device in a single pass. Devices not
// supporting discard requests fail silently, unexpected failures, such as "device in us" exit immediately.
// Runs without '--force' on to prevent accidentally trimming an in-use disk.
func discardDevice(s *sys.System, device string) error {
_, err := s.Runner().Run("blkdiscard", device)
if err == nil {
return nil
}

var exitErr *exec.ExitError
if errors.As(err, &exitErr) && exitErr.ExitCode() == blkdiscardNotSupported {
s.Logger().Warn("Device '%s' does not support discard, continuing without trimming it", device)
return nil
}
return fmt.Errorf("failed discarding device '%s': %w", device, err)
}

// runSystemdRepart runs systemd-repart for the given partitions and target device. It appends to the generated command the
Expand Down