Files
Kierán Meinhardt 669ca49ae4 disk-deactivate: wipe raid arrays before stopping them
Previously, the `disk-deactivate` script stopped mdadm arrays before
wiping the underlying physical disks. This caused filesystems with
backup superblocks (like BTRFS at 64 MiB and 256 GiB offsets) to
survive the wipe, as the backups were striped across the physical
disks and missed by `wipefs` on the raw block devices.

When the array was reassembled during reprovisioning, the filesystem
superblocks realigned. `disko` would detect the old filesystem via
`blkid` and silently skip the `mkfs` step, leaving stale data intact.

This commit adds a `wipefs --all` command against the assembled RAID
device *before* stopping it, ensuring all filesystem signatures and
backup superblocks are cleanly destroyed.
2026-04-08 09:40:37 +02:00

96 lines
2.8 KiB
Plaintext

def shellquote:
gsub("'"; "''\\''") |
"'" + . + "'"
;
# since lsblk lacks zfs support, we have to do it this way
def remove:
if .fstype == "zfs_member" then
"if type zpool >/dev/null; then zpool destroy -f \(.label); zpool labelclear -f \(.label); fi"
elif .fstype == "LVM2_member" then
[
"vg=$(pvs \(.path | shellquote) --noheadings --options vg_name | grep -o '[a-zA-Z0-9-]*')",
"vgchange -a n \"$vg\"",
"vgremove -f \"$vg\""
]
elif .fstype == "swap" then
"swapoff \(.path | shellquote)"
elif .fstype == null then
# maybe its zfs
[
# the next line has some horrible escaping
"zpool=$(if type zdb >/dev/null; then zdb -l \(.path | shellquote) | sed -nr $'s/ +name: \\'(.*)\\'/\\\\1/p'; fi)",
"if [[ -n \"${zpool}\" ]]; then zpool destroy -f \"$zpool\"; zpool labelclear -f \"$zpool\"; fi",
"unset zpool"
]
else
[]
end
;
def deactivate:
if .type == "disk" or .type == "loop" then
[
# If this disk is a member of raid, stop that raid
"md_dev=$(lsblk \(.path | shellquote) -l -p -o type,name | awk 'match($1,\"raid.*\") {print $2}')",
"if [[ -n \"${md_dev}\" ]]; then umount \"$md_dev\"; mdadm --stop \"$md_dev\"; fi",
# Remove all file-systems and other magic strings
"wipefs --all -f \(.path | shellquote)",
# Remove the MBR bootstrap code
"dd if=/dev/zero of=\(.path | shellquote) bs=440 count=1"
]
elif .type == "part" then
[
"wipefs --all -f \(.path | shellquote)"
]
elif .type == "crypt" then
[
"cryptsetup luksClose \(.path | shellquote)",
"wipefs --all -f \(.path | shellquote)"
]
elif .type == "swap" then
[
"swapoff \(.path | shellquote)"
]
elif .type == "lvm" then
(.name | split("-")[0]) as $vgname |
(.name | split("-")[1]) as $lvname |
[
"lvremove -fy \($vgname)/\($lvname)"
]
elif (.type | contains("raid")) then
[
"wipefs --all -f \(.path | shellquote)",
"mdadm --stop \(.name | shellquote)"
]
else
["echo Warning: unknown type '\(.type)'. Consider handling this in https://github.com/nix-community/disko/blob/master/disk-deactivate/disk-deactivate.jq"]
end
;
def walk:
[
(.mountpoints[] | select(. != null) | "umount -R \(. | shellquote)"),
((.children // []) | map(walk)),
remove,
deactivate
]
;
def init:
"/dev/\(.name)" as $disk |
"/dev/disk/by-id/\(."id-link")" as $disk_by_id |
"/dev/disk/by-id/\(.tran)-\(.id)" as $disk_by_id2 |
"/dev/disk/by-id/\(.tran)-\(.wwn)" as $disk_by_wwn |
if $disk == $disk_to_clear or $disk_by_id == $disk_to_clear or $disk_by_id2 == $disk_to_clear or $disk_by_wwn == $disk_to_clear then
[
"set -fu",
walk
]
else
[]
end
;
.blockdevices | map(init) | flatten | join("\n")