Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,37 @@ done
chmod +x /mnt.sh

mkdir -p /mnt/data
if [ -e /dev/disk/by-label/data-volume ]; then
# Find which disk is data volume on
DATA_DISK=$(blkid | grep "data-volume" | awk '{split($0,s,":"); sub(/\d$/, "", s[1]); print s[1]};')

# Resolve the data volume device via blkid, not the udev symlink.
# The /dev/disk/by-label/ symlink depends on udev having probed the device.
# A race between growpart (which triggers a partition table re-read and thus
# a udev re-probe) and e2fsck (which modifies the superblock) can cause the
# re-probe to see an inconsistent ext4 checksum and delete the symlink.
# BusyBox blkid doesn't support --label, so we parse the output instead.
# The leading whitespace anchor on LABEL= avoids matching PARTLABEL= on
# util-linux blkid output; quitting after the first match prevents a
# multi-match from producing a newline-separated device list.
DATA_VOLUME=$(blkid | sed -n '/[[:space:]]LABEL="data-volume"/{s/^\([^:]*\):.*/\1/p;q;}')

if [ -n "${DATA_VOLUME}" ]; then
DATA_DISK="/dev/$(lsblk --noheadings --output pkname "${DATA_VOLUME}")"
# growpart command may be missing in older VMs
if command -v growpart >/dev/null 2>&1 && command -v resize2fs >/dev/null 2>&1; then
# Automatically expand the data volume filesystem
growpart "$DATA_DISK" 1 || true
# growpart triggers a partition table re-read; settle udev before
# touching the device to avoid racing with the re-probe. The
# settle is defense-in-depth (blkid above eliminates the core
# udev dependency), so tolerate its failure rather than crashing
# the boot under set -e if udevadm is missing or stuck.
udevadm settle || true
# Only resize when filesystem is in a healthy state
if e2fsck -f -p /dev/disk/by-label/data-volume; then
resize2fs /dev/disk/by-label/data-volume || true
if e2fsck -f -p "${DATA_VOLUME}"; then
resize2fs "${DATA_VOLUME}" || true
fi
fi
# Mount data volume
mount -t ext4 /dev/disk/by-label/data-volume /mnt/data
mount -t ext4 "${DATA_VOLUME}" /mnt/data
# Update /etc files that might have changed during this boot
cp /etc/network/interfaces /mnt/data/etc/network/
cp /etc/resolv.conf /mnt/data/etc/
Expand All @@ -85,34 +102,43 @@ else
# Find an unpartitioned disk and create data-volume
DISKS=$(lsblk --list --noheadings --output name,type | awk '$2 == "disk" {print $1}')
for DISK in ${DISKS}; do
IN_USE=false
# Looking for a disk that is not mounted or partitioned
# shellcheck disable=SC2013
for PART in $(awk '/^\/dev\// {gsub("/dev/", ""); print $1}' /proc/mounts); do
if [ "${DISK}" == "${PART}" ] || [ -e /sys/block/"${DISK}"/"${PART}" ]; then
IN_USE=true
break
fi
done
if [ "${IN_USE}" == "false" ]; then
echo 'type=83' | sfdisk --label dos /dev/"${DISK}"
PART=$(lsblk --list /dev/"${DISK}" --noheadings --output name,type | awk '$2 == "part" {print $1}')
mkfs.ext4 -L data-volume /dev/"${PART}"
mount -t ext4 /dev/disk/by-label/data-volume /mnt/data
# setup apk package cache
mkdir -p /mnt/data/apk/cache
mkdir -p /etc/apk
ln -s /mnt/data/apk/cache /etc/apk/cache
# Move all persisted directories to the data volume
for DIR in ${DATADIRS}; do
DEST="/mnt/data$(dirname "${DIR}")"
mkdir -p "${DIR}" "${DEST}"
mv "${DIR}" "${DEST}"
done
# Make sure all data moved to the persistent volume has been committed to disk
sync
break
# A disk is in use if it has any partitions, carries a filesystem
# signature directly, or is mounted. Check lsblk for partitions
# and filesystem types, not just /proc/mounts; an unmounted but
# partitioned or raw-formatted disk (e.g. the data volume after
# a failed boot) must not be reformatted.
if lsblk --list --noheadings --output fstype /dev/"${DISK}" | grep --quiet "[^[:space:]]"; then
continue
fi
if lsblk --list --noheadings --output type /dev/"${DISK}" | grep --quiet "part"; then
continue
fi
if awk '/^\/dev\// {sub("^/dev/", "", $1); print $1}' /proc/mounts | grep --quiet "^${DISK}$"; then
continue
fi
echo 'type=83' | sfdisk --label dos /dev/"${DISK}"
PART=$(lsblk --list /dev/"${DISK}" --noheadings --output name,type | awk '$2 == "part" {print $1}')
mkfs.ext4 -L data-volume /dev/"${PART}"
# Let udev process the new filesystem before continuing; mount
# uses the device path directly, but later boot scripts or
# services may depend on the /dev/disk/by-label/ symlink.
# Tolerate failure so a missing or stuck udevadm does not crash
# the boot under set -e.
udevadm settle || true
mount -t ext4 /dev/"${PART}" /mnt/data
# setup apk package cache
mkdir -p /mnt/data/apk/cache
mkdir -p /etc/apk
ln -s /mnt/data/apk/cache /etc/apk/cache
# Move all persisted directories to the data volume
for DIR in ${DATADIRS}; do
DEST="/mnt/data$(dirname "${DIR}")"
mkdir -p "${DIR}" "${DEST}"
mv "${DIR}" "${DEST}"
done
# Make sure all data moved to the persistent volume has been committed to disk
sync
break
done
fi
for DIR in ${DATADIRS}; do
Expand Down