From 1793b582f6cf5bf5296a5ad50bb8d838a6e1e1d4 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Tue, 25 Aug 2026 21:18:03 -0400 Subject: [PATCH 1/2] grow-var: resolve the whole disk with lsblk -d; refuse anything else `lsblk -no PKNAME ` also lists the partition's holders, and for a dm slave the dm child's row comes first - its PKNAME is the partition itself. On an encrypted /var this resolved "disk" to /dev/nvme0n1p16 and `sgdisk -e` then wrote a fresh GPT over the LUKS2 header (primary at 0, secondary at 16 KiB both destroyed; the mapping survived only because the key was already in the kernel). Observed on a Jetson Orin Nano on the first encrypted-/var boot; the plaintext path never hit it because there the var device is the partition and lsblk's first row is its own. Use -d (no dependents) and, before sgdisk touches anything, require the resolved device to be of TYPE disk. Claude-Session: https://claude.ai/code/session_01AqE5abpz1hSdeM9ZCRLLrf --- overlays/base/usr/bin/avocado-grow-var | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/overlays/base/usr/bin/avocado-grow-var b/overlays/base/usr/bin/avocado-grow-var index 15f810c..53a48fe 100755 --- a/overlays/base/usr/bin/avocado-grow-var +++ b/overlays/base/usr/bin/avocado-grow-var @@ -40,8 +40,17 @@ if [ -n "$dm_dev" ]; then : "${blk_dev:=$var_dev}" fi -disk=/dev/$(lsblk -no PKNAME "$blk_dev" | head -n 1) +# -d (no dependents): without it lsblk also lists the partition's holders, and +# for a dm slave the dm child's row comes first - its PKNAME is the partition +# itself, so "disk" resolved to /dev/nvme0n1p16 and `sgdisk -e` wrote a GPT +# over the LUKS2 header (observed on a Jetson Orin Nano with encrypted /var). +disk=/dev/$(lsblk -dno PKNAME "$blk_dev") part=$(printf '%s\n' "$blk_dev" | grep -oE '[0-9]+$') +# Never let sgdisk near anything that is not a whole disk holding a table. +if [ "$(lsblk -dno TYPE "$disk" 2>/dev/null)" != "disk" ]; then + echo "grow-var: $disk (parent of $blk_dev) is not a whole disk; refusing to touch it." >&2 + exit 1 +fi ptable=$(lsblk -dno PTTYPE "$disk") echo "grow-var: $var_dev (via $blk_dev) on $disk (partition $part, $ptable table)." From 78cf80438a608f179f589b0a3c796f666cf747c4 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Wed, 26 Aug 2026 10:34:04 -0400 Subject: [PATCH 2/2] grow-var: read sector counts from sysfs, blockdev is not in the runtime The LUKS branch used blockdev --getsz, which util-linux-blockdev provides and the image does not ship: on a Jetson AGX Thor with encrypted /var the partition was extended and then the unit died with 'line 128: blockdev: command not found' (status 127) before the dm/partition size comparison. /sys/class/block//size is the same 512-byte sector count for both the partition and the dm-N node behind /dev/mapper/var. --- overlays/base/usr/bin/avocado-grow-var | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/overlays/base/usr/bin/avocado-grow-var b/overlays/base/usr/bin/avocado-grow-var index 53a48fe..2f4716d 100755 --- a/overlays/base/usr/bin/avocado-grow-var +++ b/overlays/base/usr/bin/avocado-grow-var @@ -124,9 +124,11 @@ if [ "$blk_dev" != "$var_dev" ]; then # resize cannot happen here. The initramfs (cryptsetup-var.sh) already # handles LUKS resize when it detects partition_sectors > dm_sectors on # the next boot — with the key still available at that point. + # Sizes from sysfs: blockdev(8) is not in the runtime image. + sectors() { cat "/sys/class/block/$(basename "$(readlink -f "$1")")/size"; } data_offset=$(dmsetup table "$dm_name" | awk '{print $8}') - expected_dm=$(( $(blockdev --getsz "$blk_dev") - data_offset )) - dm_sectors=$(blockdev --getsz "$var_dev") + expected_dm=$(( $(sectors "$blk_dev") - data_offset )) + dm_sectors=$(sectors "$var_dev") if [ "$dm_sectors" -lt "$expected_dm" ]; then echo "grow-var: LUKS container ($dm_sectors sectors) < partition ($expected_dm sectors)." echo "grow-var: partition extended — cryptsetup-var.sh will resize LUKS + btrfs on next boot."