Fix partition issue
This commit is contained in:
1 parent
7c50d72f40
commit
7d3b01eae9
5 files changed
+424
-64
No files matched your search
@@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# create_partition() must report the number parted actually assigned, never a
|
||||
# predicted one. The regression this pins: the configurator used to compute
|
||||
# "highest existing partition + 1", while parted fills the lowest free GPT
|
||||
# slot. Any disk whose numbering has a hole — what deleting a partition to
|
||||
# free space leaves behind — then had every later command (cryptsetup, mkfs,
|
||||
# mount) pointed at device nodes that did not exist, surfacing much later as
|
||||
# "protected mode: /mnt is not a mountpoint".
|
||||
#
|
||||
# parted operates on image files directly, so this needs no root, no loop
|
||||
# devices, and no real disk.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
LIB="$ROOT/configs/airootfs/usr/share/omarchy-iso/disk-partitioning.sh"
|
||||
|
||||
if ! command -v parted >/dev/null 2>&1; then
|
||||
echo "SKIP: parted is not installed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# shellcheck source=../configs/airootfs/usr/share/omarchy-iso/disk-partitioning.sh
|
||||
source "$LIB"
|
||||
|
||||
WORK=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK"' EXIT
|
||||
|
||||
IMG="$WORK/disk.img"
|
||||
MIB=$((1024 * 1024))
|
||||
failures=0
|
||||
|
||||
check() {
|
||||
local label="$1" expected="$2" actual="$3"
|
||||
if [[ $expected == "$actual" ]]; then
|
||||
printf ' ok %s\n' "$label"
|
||||
else
|
||||
printf ' FAIL %s: expected %s, got %s\n' "$label" "$expected" "$actual"
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
# parted reports a partition's size inclusive of both endpoints, so it lands
|
||||
# one sector above (end - start). Same slack create_partition allows.
|
||||
check_size() {
|
||||
local label="$1" want="$2" actual="${3:-0}" delta
|
||||
delta=$((actual - want))
|
||||
(( delta < 0 )) && delta=$((-delta))
|
||||
if (( delta <= MIB )); then
|
||||
printf ' ok %s\n' "$label"
|
||||
else
|
||||
printf ' FAIL %s: expected ~%s, got %s\n' "$label" "$want" "$actual"
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
# parted's end position is inclusive, so partitions laid back to back overlap
|
||||
# by a sector and are refused. Leave a MiB between them.
|
||||
mkpart_mib() {
|
||||
parted --script "$IMG" mkpart "$1" "$2" "$(($3 * MIB))B" "$(($4 * MIB))B"
|
||||
}
|
||||
|
||||
# A disk with holes: four partitions, then delete the middle two. Slots 2 and
|
||||
# 3 are free while the highest number in use is 4 — the shape of the reported
|
||||
# failure, where the user deleted a partition to make room.
|
||||
build_holey_disk() {
|
||||
rm -f "$IMG"
|
||||
truncate -s 4G "$IMG"
|
||||
parted --script "$IMG" mklabel gpt
|
||||
mkpart_mib one ext4 1 200
|
||||
mkpart_mib two ext4 201 400
|
||||
mkpart_mib three ext4 401 600
|
||||
mkpart_mib four ext4 601 800
|
||||
parted --script "$IMG" rm 2
|
||||
parted --script "$IMG" rm 3
|
||||
created_parts=()
|
||||
}
|
||||
|
||||
echo "==> numbering on a disk with holes"
|
||||
build_holey_disk
|
||||
check "existing numbers" "1 4" "$(partition_numbers "$IMG" | sort | tr '\n' ' ' | sed 's/ $//')"
|
||||
|
||||
create_partition "$IMG" "$((1000 * MIB))" "$((1200 * MIB))" fat32 OMARCHY_EFI
|
||||
check "create_partition succeeded (esp)" "0" "$?"
|
||||
esp_num="$created_partition_number"
|
||||
check "esp took the lowest free slot" "2" "$esp_num"
|
||||
|
||||
# Starts a MiB past the ESP, the way run_partition_decide aligns ROOT_START_B
|
||||
# up from EFI_END_B + 1.
|
||||
create_partition "$IMG" "$((1201 * MIB))" "$((2000 * MIB))" btrfs OMARCHY_ROOT
|
||||
check "create_partition succeeded (root)" "0" "$?"
|
||||
root_num="$created_partition_number"
|
||||
check "root took the next free slot" "3" "$root_num"
|
||||
|
||||
# The old prediction. If either of these ever matches again, the regression is
|
||||
# back: the highest number in use was 4, so the guess would have been 5 and 6.
|
||||
check "esp is not the predicted number" "not-5" "$([[ $esp_num == 5 ]] && echo 5 || echo not-5)"
|
||||
check "root is not the predicted number" "not-6" "$([[ $root_num == 6 ]] && echo 6 || echo not-6)"
|
||||
|
||||
check "both creations tracked for rollback" "2 3" "${created_parts[*]}"
|
||||
check_size "esp size" "$((200 * MIB))" "$(partition_size_bytes "$IMG" "$esp_num")"
|
||||
check_size "root size" "$((799 * MIB))" "$(partition_size_bytes "$IMG" "$root_num")"
|
||||
|
||||
echo "==> rollback reclaims only what this run created"
|
||||
rollback_created_parts "$IMG"
|
||||
check "created partitions removed" "1 4" "$(partition_numbers "$IMG" | sort | tr '\n' ' ' | sed 's/ $//')"
|
||||
check "rollback list cleared" "0" "${#created_parts[@]}"
|
||||
|
||||
echo "==> numbering on a disk without holes"
|
||||
rm -f "$IMG"
|
||||
truncate -s 4G "$IMG"
|
||||
parted --script "$IMG" mklabel gpt
|
||||
mkpart_mib one ext4 1 200
|
||||
mkpart_mib two ext4 201 400
|
||||
created_parts=()
|
||||
|
||||
create_partition "$IMG" "$((1000 * MIB))" "$((1200 * MIB))" fat32 OMARCHY_EFI
|
||||
check "appends when there is no hole" "3" "$created_partition_number"
|
||||
|
||||
echo "==> a refused creation stays out of the rollback list"
|
||||
created_parts=()
|
||||
create_partition "$IMG" "$((100 * MIB))" "$((300 * MIB))" ext4 OVERLAP
|
||||
check "overlapping creation failed" "1" "$?"
|
||||
check "nothing tracked" "0" "${#created_parts[@]}"
|
||||
|
||||
if (( failures > 0 )); then
|
||||
printf '\n%d check(s) failed\n' "$failures"
|
||||
exit 1
|
||||
fi
|
||||
printf '\nall checks passed\n'
|
||||
Reference in new issue
Block a user