image-ddi: Mount persistent storage from internal/rw LVM LV

This commit is contained in:
Tobias Waldekranz
2026-03-08 21:56:45 +00:00
parent 3f23aa92be
commit ea315bdb10
3 changed files with 226 additions and 0 deletions
@@ -0,0 +1,15 @@
tmpfs /tmp tmpfs mode=0755,nosuid,nodev 0 0
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
tmpfs /media tmpfs mode=1755,nosuid,nodev 0 0
tmpfs /mnt/tmp tmpfs defaults 0 0
# Locate and mount /cfg, /home, /root and /var from the internal
# volume, wherever that is located - or, as a last resort, setup tmpfs
# mounts at these points. Setup an ephemeral writable overlay on /etc.
/usr/libexec/infix/mnt# /mnt/rw helper none 0 0
# Optional, nice-to-have mounts
debugfs /sys/kernel/debug debugfs nofail 0 0
tracefs /sys/kernel/tracing tracefs nofail 0 0
cfgfs /config configfs nofail,noauto 0 0
host /mnt/host 9p nofail,noauto,cache=none,msize=16384 0 0
+211
View File
@@ -0,0 +1,211 @@
#!/bin/sh
# Called from /etc/fstab to ensure we have something writable mounted
# at /cfg, /home, /root, and /var.
#
# In the normal case, the "rw" LV from the "internal" LVM VG is used
# to back all persistant storage. In the event that "internal" is
# present, but the "rw" LV is missing, one will be provisioned, along
# with the required BTRFS subvolumes.
#
# In all other scenarios where the subvolumes are not available, the
# system will fall back to temporary storage for all mount points.
#
# For /etc, a writable, tmpfs backed, layer is always overlayed on top
# of the read-only contents from the OS image.
set -e
nm=$(basename "$0")
need_restore=
code=0
logmsg()
{
logger -k -t "$nm" -p user.crit "$@"
}
status()
{
GREEN="$(printf '\033[1;32m')"
RED="$(printf '\033[1;31m')"
YELLOW="$(printf '\033[1;33m')"
BOLD="$(printf '\033[1m')"
RESET="$(printf '\033[0m')"
case $1 in
0) color=$GREEN; text=' OK ' ;;
1) color=$RED; text='FAIL' ;;
2) color=$YELLOW;text='WARN' ;;
*) color=$YELLOW;text=' ⋯ ' ;;
esac
printf '%s[%s%s%s%s]%s ' "$BOLD" "$color" "$text" "$RESET" "$BOLD" "$RESET"
}
print_start()
{
printf '\r\033[K%s%s' "$(status 3)" "$*" > /dev/console
need_restore=YES
}
print_end()
{
rc=$1; shift
if [ $# -gt 0 ]; then
printf '\r\033[K%s%s\n' "$(status "$rc")" "$*" > /dev/console
else
printf '\r%s\n' "$(status "$rc")" > /dev/console
fi
}
# Restore Finit's original progress message so its [ OK ] appears correctly
print_restore()
{
[ "$need_restore" ] || return 0
print_start "Mounting filesystems from /etc/fstab"
}
# # External button or bootloader changed kernel command line
# check_factory()
# {
# if [ -f /mnt/cfg/infix/.reset ]; then
# return 0;
# fi
# if grep -q 'finit.cond=factory-reset' /proc/cmdline; then
# return 0;
# fi
# # Add to your br2-external to extend factory-reset check
# if [ ! -x /usr/libexec/infix/check-factory ]; then
# return 1;
# fi
# /usr/libexec/infix/check-factory
# }
# factory_reset()
# {
# find /sys/class/leds/ -type l -exec sh -c 'echo 100 > $0/brightness' {} \;
# print_start "Resetting to factory defaults."
# logger $opt -p user.notice -t "$nm" "Resetting to factory defaults."
# rm -rf /mnt/cfg/* /mnt/var/*
# sync
# logger $opt -p user.notice -t "$nm" "Factory reset complete."
# print_end 0 "Factory reset complete."
# print_restore
# }
subvols="cfg var root home"
internal_rw_provision()
{
print_start "Provisioning persistent storage on internal volume"
lvm lvcreate --name rw --extents 50%FREE internal || {
logmsg "No rw LV available, nor could it be created"
print_end 1
return 1
}
mkfs.btrfs -L rw /dev/internal/rw || {
logmsg "Could not create BTRFS on rw LV"
print_end 1
return 1
}
mount -t btrfs /dev/internal/rw /mnt/rw || {
logmsg "Failed to mount rw"
print_end 1
return 1
}
for subvol in $subvols; do
btrfs subvolume create /mnt/rw/@"$subvol" || {
logmsg "Failed to create @$subvol on rw"
print_end 1
return 1
}
done
umount /mnt/rw || {
logmsg "Failed to unmount rw"
print_end 1
return 1
}
print_end 0
}
internal_rw_activate()
{
lvm vgs internal || {
logmsg "No internal volume available"
return 1
}
lvm vgchange -ay internal || {
logmsg "Unable to bring internal volume online"
return 1
}
# The only condition under which we do BTRFS provisioning is when
# the LV is absent. In all other failure scenarios: fall back to
# tmpfs and let the user sort it out. This way we do not risk any
# loss of data.
[ -b /dev/internal/rw ] && return 0
internal_rw_provision
}
internal_rw_mount()
{
internal_rw_activate || return 1
for subvol in $subvols; do
mount -t btrfs /dev/internal/rw /"$subvol" -o subvol=@"$subvol" || {
logmsg "Failed to mount /$subvol"
return 1
}
done
}
tmpfs_rw_mount()
{
for subvol in $subvols; do
mkdir -p -m 0755 /mnt/tmp/"$subvol"
mount /mnt/tmp/"$subvol" /"$subvol" -o bind || {
logmsg "Failed to mount temporary /$subvol"
return 1
}
done
}
tmpfs_etc_mount()
{
mkdir -p -m 0755 /mnt/tmp/etc/
tar c -C /etc . | tar x -C /mnt/tmp/etc
mount /mnt/tmp/etc /etc -o bind
}
exec >/mnt/tmp/mnt.log 2>&1
tmpfs_etc_mount || {
code=1
logmsg "Failed to make /etc writable"
}
if ! internal_rw_mount; then
code=1
print_end 1 "Mounting persistent storage from internal volume"
logmsg "Internal volume not found, falling back to tmpfs"
print_start "Falling back to ephemeral tmpfs storage!"
tmpfs_rw_mount
print_end $?
fi
print_restore
exit $code