From b67d86c6d37bb0b5417cfa95506982dae87b95db Mon Sep 17 00:00:00 2001 From: Jonathan Bauer Date: Mon, 18 Nov 2019 11:53:24 +0100 Subject: [slx-dmsetup] dedicated tmpfs for cow fallback --- builder/modules.d/slx-dmsetup/module-setup.sh | 2 +- .../slx-dmsetup/scripts/dmsetup-slx-device | 34 +++++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/builder/modules.d/slx-dmsetup/module-setup.sh b/builder/modules.d/slx-dmsetup/module-setup.sh index 68e9b7b4..001104aa 100755 --- a/builder/modules.d/slx-dmsetup/module-setup.sh +++ b/builder/modules.d/slx-dmsetup/module-setup.sh @@ -11,7 +11,7 @@ install() { inst_hook pre-pivot 10 "$moddir/scripts/generate-fstab-swap.sh" inst_hook pre-pivot 00 "$moddir/scripts/grow-rootfs.sh" # deliberatly left ext helpers out for now, since we don't really use it. - inst_multiple blockdev xxd \ + inst_multiple blockdev fallocate xxd \ mkfs.ext4 resize2fs \ xfs_repair xfs_growfs } diff --git a/builder/modules.d/slx-dmsetup/scripts/dmsetup-slx-device b/builder/modules.d/slx-dmsetup/scripts/dmsetup-slx-device index 7a371123..89dab344 100755 --- a/builder/modules.d/slx-dmsetup/scripts/dmsetup-slx-device +++ b/builder/modules.d/slx-dmsetup/scripts/dmsetup-slx-device @@ -133,10 +133,36 @@ create_snapshot() { # This will call terminate the whole script by calling finish_setup, if successful ramdisk_fallback() { echo "$0: Falling back to regular dm-snapshot on a RAMdisk." - local file="$(mktemp -u -p /run/openslx dnbd_cow.XXX)" - local size="$SLX_RAMDISK_SIZE_IN_MB" - [ -z "$size" ] && size="$(awk '/MemTotal/ {printf("%d\n", $2 / 2 / 1024 )}' /proc/meminfo)" - dd of="$file" seek="$size" bs=1M count=0 &> /dev/null + # first we create a dedicated tmpfs to control the maximum size + local cow_tmpfs="/run/openslx/dnbd-cow" + if ! mkdir -p "$cow_tmpfs"; then + cow_tmpfs="${cow_tmpfs}.$$" + if ! mkdir -p "$cow_tmpfs"; then + # ultimate fallback on regular /run/openslx + cow_tmpfs="/run/openslx" + fi + fi + + local qcow_size_in_kb="$(( writable_device_size / 2 ))" + local ram_size_in_kb="$(awk '/MemTotal/ {printf("%d\n", $2 )}' /proc/meminfo)" + + # Use the qcow size + half the RAM as tmpfs size. + local cow_size="$(( qcow_size_in_kb + ( ram_size_in_kb / 2 ) ))" + if ! mount -t tmpfs tmpfs -o size="${cow_size}k" "$cow_tmpfs"; then + emergency_shell "Failed to prepare dedicated CoW tmpfs in $cow_tmpfs of size $cow_size." + fi + + local file="$(mktemp -u -p "$cow_tmpfs" dnbd_cow.XXX)" + local fail_count=0 + while ! fallocate -l "${cow_size}K" "$file" ; do + (( cow_size -= 4 )) + if [ "$(( fail_count ++ ))" -eq 1000 ]; then + break + fi + done + if [ "$fail_count" -eq 1000 ]; then + emergency_shell "Failed to allocate CoW file $file after 1000 tries. :(" + fi writable_device="$(losetup --show --find "$file")" cow_device_candidate="root" while [ -b "/dev/mapper/$cow_device_candidate" ]; do -- cgit v1.2.3-55-g7522