Partition handling for disks with 4k sectors broke partition resizing when using MBR disk label. It seems that sfdisk doesn't calculate the last LBA for diks with MBR label. Calculate the last usable LBA ourselfs in the MBR case.
70 lines
2.8 KiB
Bash
Executable File
70 lines
2.8 KiB
Bash
Executable File
#!/bin/sh
|
|
# ==============================================================================
|
|
# HassOS partition expander
|
|
# ==============================================================================
|
|
set -e
|
|
|
|
DEVICE_CHILD="$(findfs LABEL="hassos-data")"
|
|
DEVICE_CHILD_NAME="$(basename "${DEVICE_CHILD}")"
|
|
DEVICE_ROOT_NAME="$(lsblk -no pkname "${DEVICE_CHILD}")"
|
|
DEVICE_ROOT="/dev/${DEVICE_ROOT_NAME}"
|
|
PART_NUM="$(cat "/sys/class/block/${DEVICE_CHILD_NAME}/partition")"
|
|
|
|
# Get partition label type
|
|
PART_TABLE="$(sfdisk -lqJ "${DEVICE_ROOT}")"
|
|
PART_LABEL="$(echo "${PART_TABLE}" | jq -r '.partitiontable.label')"
|
|
echo "[INFO] Checking if expanding data partition on ${DEVICE_CHILD} is necessary"
|
|
|
|
if [ "${PART_LABEL}" = "gpt" ]; then
|
|
echo "[INFO] Detected GPT partition label on ${DEVICE_ROOT}"
|
|
|
|
if sfdisk --verify "${DEVICE_ROOT}" 2>&1 | grep "The backup GPT table is not on the end of the device."; then
|
|
echo "[INFO] Moving GPT backup header to the end"
|
|
sfdisk --relocate gpt-bak-std "${DEVICE_ROOT}"
|
|
|
|
# Reload partition label to get correct .partitiontable.lastlba
|
|
PART_TABLE="$(sfdisk -lqJ "${DEVICE_ROOT}")"
|
|
fi
|
|
LAST_USABLE_LBA="$(echo "${PART_TABLE}" | jq -r '.partitiontable.lastlba')"
|
|
else
|
|
echo "[INFO] Detected MBR partition label on ${DEVICE_ROOT}"
|
|
|
|
# For MBR, we have to calculate the last usable sector by ourselfs
|
|
DEVICE_SIZE=$(blockdev --getsize64 "${DEVICE_ROOT}")
|
|
SECTOR_SIZE=$(echo "${PART_TABLE}" | jq -r '.partitiontable.sectorsize')
|
|
LAST_USABLE_LBA="$((DEVICE_SIZE / SECTOR_SIZE))"
|
|
fi
|
|
echo "[INFO] Last usable logical block ${LAST_USABLE_LBA}"
|
|
|
|
# Calculate end of data partition
|
|
JQ_FILTER=".partitiontable.partitions[] | select ( .node == \"${DEVICE_CHILD}\" ) | .start + .size"
|
|
DATA_PARTITION_END="$(echo "${PART_TABLE}" | jq "${JQ_FILTER}")"
|
|
echo "[INFO] Data partition end block ${DATA_PARTITION_END}"
|
|
|
|
# Need resize? Ignore free space if its less than 8MB/64MB (4k sectors) since
|
|
# that could be partition alignment rounding...
|
|
UNUSED_BLOCKS=$(( LAST_USABLE_LBA - DATA_PARTITION_END ))
|
|
if [ "${UNUSED_BLOCKS}" -le "16384" ]; then
|
|
echo "[INFO] No resize of data partition needed"
|
|
exit 0
|
|
fi
|
|
|
|
echo "[INFO] Update hassos-data partition ${PART_NUM}"
|
|
echo ", +" | sfdisk --no-reread --no-tell-kernel -N "${PART_NUM}" "${DEVICE_ROOT}"
|
|
sfdisk -V "${DEVICE_ROOT}"
|
|
|
|
# Update the kernel's partition table
|
|
partx -u "${DEVICE_ROOT}"
|
|
udevadm settle
|
|
|
|
# Make sure /dev/disk/by-label/hassos-data is actually present before exiting.
|
|
# This avoids a race condition with mnt-data.mount which might fail to bind
|
|
# otherwise:
|
|
# Bound to unit dev-disk-by\x2dlabel-hassos\x2ddata.device, but unit isn't active.
|
|
if ! systemctl start "dev-disk-by\\x2dlabel-hassos\\x2ddata.device"; then
|
|
echo "[ERROR] Data partition not found!"
|
|
exit 1
|
|
fi
|
|
|
|
echo "[INFO] Finished hassos-data partition resizing"
|