summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xmodules.d/slx-dmsetup/hooks/dmsetup-slx-device291
1 files changed, 179 insertions, 112 deletions
diff --git a/modules.d/slx-dmsetup/hooks/dmsetup-slx-device b/modules.d/slx-dmsetup/hooks/dmsetup-slx-device
index 9da7ea44..7cf4df64 100755
--- a/modules.d/slx-dmsetup/hooks/dmsetup-slx-device
+++ b/modules.d/slx-dmsetup/hooks/dmsetup-slx-device
@@ -24,7 +24,9 @@ exec {BASH_XTRACEFD}> /run/openslx/dmsetup.log
set -x
# read-only device to prepare for CoW
-[ -z "$1" ] && emergency_shell "Read-only device was not given!"
+[ -n "$1" ] || emergency_shell "Read-only device was not given!"
+[ -b "$1" ] || emergency_shell "Given device '$1' does not exist or is not block device"
+
declare -g read_only_device="$1"
declare -g read_only_device_sz="$( blockdev --getsz "$1" )"
# Use _sz suffix for sizes expressed in number of 512b sectors,
@@ -59,18 +61,22 @@ handle_unit() {
parse_config() {
local remaining_device_sz="$writable_device_sz"
+ # First, handle absolute definitions
parse_config_int "$1" 0
+ # Then, distribute relative values to remaining space
parse_config_int "$1" 1
}
# global array variables storing the configuration of the partitions
-declare -ag linear snapshot thin_snapshot thin_volume
+declare -ag linear thin_volume
+snapshot=
+thin_snapshot=
parse_config_int() {
[ -z "$1" ] && return 1
local -i rel_only="$2"
while IFS= read -r line || [ -n "$line" ]; do
[ -z "$line" ] && continue
- read -r type name range crypt ignore <<< "$line"
+ read -r type name range crypt _ <<< "$line"
type=${type//-/_} # to use the type as variable in eval
if ! [[ "$type" =~ \
^(linear|snapshot|thin_snapshot|thin_volume)$ ]]; then
@@ -124,9 +130,16 @@ parse_config_int() {
# finally save it to the global array for this type
case "$type" in
linear) linear+=("${name} ${crypt} ${min} ${max}") ;;
- snapshot) snapshot+=("${name} ${crypt} ${min} ${max}") ;;
- thin_snapshot) thin_snapshot+=("${name} ${crypt} ${min} ${max}") ;;
thin_volume) thin_volume+=("${name} ${crypt} ${min} ${max}") ;;
+ # Special - rootfs, only one makes sense
+ snapshot)
+ [ -n "$snapshot" ] && echo "Warning: More than one snapshot declared!" >&2
+ snapshot="${name} ${crypt} ${min} ${max}"
+ ;;
+ thin_snapshot)
+ [ -n "$thin_snapshot" ] && echo "Warning: More than one thin_snapshot declared!" >&2
+ thin_snapshot="${name} ${crypt} ${min} ${max}"
+ ;;
*) echo "$0: SOMETHING NOT GOOT CHECK SOURCE CODE" ;;
esac
# Decrease for upcoming calculations if we used fixed values here
@@ -149,55 +162,79 @@ dmsetup_create_noudevsync() {
dmsetup create "$1" --noudevsync
fi
dmsetup mknodes --noudevsync "$1"
+ echo "dm: Created $1"
)
local ret=$?
[ -b "/dev/mapper/$1" ] || ret=99
- [ $ret -ne 0 ] && dmsetup remove --noudevsync "$1"
+ if [ $ret -ne 0 ]; then
+ echo "dm: Error creating $1, removing..."
+ dmsetup remove --noudevsync "$1"
+ fi
return $ret
}
# encrypt_device <dev_path> <encrypted_name> [<start> <size>]
encrypt_device() {
# TODO: Send key back to us, demand ransom
- modprobe dm-crypt || echo "$0: dm-crypt loading failed, maybe builtin?"
- [ -b "$1" ] || return 1
- [ -n "$2" ] || return 1
+ modprobe dm-crypt || echo "encrypt: dm-crypt loading failed, maybe builtin?"
+ if ! [ -b "$1" ]; then
+ echo "encrypt: Not block device: '$1'"
+ return 1
+ fi
+ if [ -z "$2" ]; then
+ echo "encrypt: No name given"
+ return 1
+ fi
local dev_size="$( blockdev --getsz "$1" )"
if [ -z "$dev_size" ]; then
- echo "$0: Cannot encrypt non-existent device $1"
+ echo "encrypt: Cannot get size of $1"
return 1
fi
- local size="$4"
- local start="$3"
- # Sanitize
- [ "$start" -ge 0 ] 2> /dev/null || start=0
- [ "$size" -gt 0 ] 2> /dev/null || size="$dev_size"
+ echo "encrypt: Encrypting device $1 as $2"
+ local size="${4:-0}"
+ local start="${3:-0}"
+ # Sanitize (negated check to catch non-numeric values)
+ if ! [ "$start" -ge 0 ] 2> /dev/null; then
+ echo "encrypt: Invalid start offset '$start', using 0"
+ start=0
+ fi
+ if ! [ "$size" -gt 0 ] 2> /dev/null; then
+ echo "encrypt: Invalid end offset '$size', using entire device"
+ size="$dev_size"
+ fi
# Put in bounds
- (( start > dev_size )) && start="$dev_size"
- (( start + size > dev_size )) && size="$(( dev_size - start ))"
+ if (( start >= dev_size )); then
+ echo "encrypt: Start offset $start past end of device ($dev_size)"
+ return 1
+ fi
+ if (( start + size > dev_size )); then
+ echo "encrypt: End offset ($start + $size) past end of device ($dev_size), truncating"
+ size="$(( dev_size - start ))"
+ fi
local key
key="$( < /dev/urandom xxd -c32 -p -l32 )"
[ -z "$key" ] && key="$( < /dev/urandom tr -c -d 'a-f0-9' | dd count=1 bs=32 )"
[ -z "$key" ] && key="$( < /dev/urandom head -c32 | xxd -c32 -p )"
[ -z "$key" ] && key="$( < /dev/urandom xxd -c32 -p | head -n 1 )"
if [ -z "$key" ]; then
- echo "$0: ERROR: Could not generate encryption key"
+ echo "encrypt: ERROR: Could not generate encryption key"
return 1
fi
if ! dmsetup_create_noudevsync "$2" \
"0 ${size} crypt aes-xts-plain64 $key 0 $1 ${start} 1 allow_discards"; then
- echo "$0: Failed to encrypt $1."
+ echo "encrypt: Failed to encrypt $1."
return 1
fi
+ echo "encrypt: Setup successful"
return 0
}
# create_snapshot "<name> <persist>" "cow_device"
create_snapshot() {
- modprobe dm-snapshot || echo "$0: dm-snapshot loading failed, maybe builtin?"
+ modprobe dm-snapshot || echo "snapshot: dm-snapshot loading failed, maybe builtin?"
read -r name persist _ <<< "$1"
+ echo "snapshot: Creating $name for $read_only_device (using $2)"
if ! dmsetup_create_noudevsync "$name" \
"0 $read_only_device_sz snapshot $read_only_device $2 ${persist:-N} 8"; then
- echo "$0: Failed to create snapshot on '$2' for '$read_only_device'."
return 1
fi
return 0
@@ -210,7 +247,7 @@ create_snapshot() {
# placed on a dedicated tmpfs.
# THIS FUNCTION MUST NEVER RETURN
ramdisk_fallback() {
- echo "$0: Falling back to regular dm-snapshot on a RAMdisk."
+ echo "ramdisk: Falling back to regular dm-snapshot on a RAMdisk."
# RAM size in kb, note that this is equal to half
# of the entire RAM when interpreted as 512-bytes sectors.
@@ -218,30 +255,30 @@ ramdisk_fallback() {
# try to prepare the zero extension device
local extended_device="/dev/mapper/${read_only_device##*/}-extended"
- (
- set -e
- lsmod | grep -q dm-zero || modprobe dm-zero
- dmsetup_create_noudevsync "${extended_device##*/}" \
- "0 $read_only_device_sz linear $read_only_device 0
- $read_only_device_sz $ram_cow_sz zero"
- )
+ modprobe dm-zero
+ dmsetup_create_noudevsync "${extended_device##*/}" <<-EOF
+ 0 $read_only_device_sz linear $read_only_device 0
+ $read_only_device_sz $ram_cow_sz zero
+ EOF
local ret="$?"
if [ "$ret" -eq 0 ]; then
read_only_device="$extended_device"
read_only_device_sz="$(( read_only_device_sz + ram_cow_sz ))"
else
- echo "$0: Failed to setup the fake larger '$read_only_device'."
- echo "$0: Continuing with its original size."
+ echo "ramdisk: Failed to setup the virtual, larger '$read_only_device'."
+ echo "ramdisk: Continuing with its original size."
fi
# prepare dedicated tmpfs mount point
+ echo "ramdisk: Preparing dedicated tmpfs"
local cow_tmpfs="/run/openslx/cow"
if ! mkdir -p "$cow_tmpfs"; then
cow_tmpfs="${cow_tmpfs}.$$.$RANDOM"
mkdir -p "$cow_tmpfs"
fi
if ! mount -t tmpfs cow-tmpfs -o size="$(( read_only_device_sz / 2 + 100 ))k" "$cow_tmpfs"; then
- echo "$0: Failed to mount tmpfs in '$cow_tmpfs' of size '$(( read_only_device_sz / 2 + 100 ))KiB', trying to use regular /run tmpfs."
+ echo "ramdisk: Failed to mount tmpfs in '$cow_tmpfs' of size '$(( read_only_device_sz / 2 + 100 ))KiB', trying to use regular /run tmpfs."
+ cow_tmpfs="/run"
fi
# create sparse file there
@@ -259,6 +296,7 @@ ramdisk_fallback() {
emergency_shell "CRITICAL: failed to setup RAMdisk fallback."
exit 1
fi
+ # [noreturn]
finish_setup "$cow_device_candidate" "0" "$read_only_device_sz"
}
@@ -314,16 +352,17 @@ save_partition_info() {
require_exact_scratch_size() {
local current_sz="$( blockdev --getsz "$scratch_device" )"
(( current_sz == scratch_device_sz )) && return 0 # Everything fine
+ echo "exact_scratch: Adding another layer; want: $scratch_device_sz, is: $current_sz"
if (( current_sz < scratch_device_sz )); then
- echo "$0: WARNING: scratch_device_sz is larger than actual device."
- echo "$0: This should never happen."
+ echo "exact_scratch: WARNING: scratch_device_sz is larger than actual device."
+ echo "exact_scratch: This should never happen."
scratch_device_sz="$current_sz"
return 0
fi
# We could check if $scratch_device already is a dm target, and just adjust its
# size, but I think that scenario isn't possible, currently.
if ! dmsetup_create_noudevsync "scratch" "0 $scratch_device_sz linear $scratch_device 0"; then
- echo "$0: Failed to create scratch space for the CoW layer."
+ echo "exact_scratch: Failed to create scratch space for the CoW layer."
return 1
fi
scratch_device="/dev/mapper/scratch"
@@ -336,17 +375,19 @@ create_pool() {
declare -r wanted_low_mb=100 # Free space below this will trigger a dm event
# create external snapshot for read-only device
# create remaining thin volumes
- modprobe dm-thin-pool || echo "$0: dm-thin-pool load failed, maybe builtin?"
+ echo "pool: Creating thinpool for cow"
+ modprobe dm-thin-pool || echo "pool: dm-thin-pool load failed, maybe builtin?"
# create temporary metadata device
# calculate number of sectors needed and check boundaries:
# XXX Formula from thin-pool.txt calculates size in *bytes*, we want 512b blocks
metadata_dev_sz="$(( 48 * scratch_device_sz / data_block_sz / 512 ))"
# If we want NTFS as a backup plan to extend the pool, check if the current size
# is less than 100GB, and only then consider this feature.
- # Maybe make that thresold configurable one day, but the the desktop client
+ # Maybe make that thresold configurable one day, but for the desktop client
# use case this is sensible for now.
if [ "$SLX_NTFSFREE" = "backup" ] && (( scratch_device_sz < 209715200 )) \
&& [ -z "$metadata_persistent" ]; then
+ echo "pool: Considering NTFS partitions as backup since pool is small"
find_ntfs_partitions
if [ -s "$ntfs_list" ]; then
# Look what size we end up if we want at least 50GB
@@ -371,9 +412,11 @@ create_pool() {
local metadata_persistent=
if [ -n "$metadata_persistent" ]; then
# create persistent slice of the writable device for the pool metadata
+ # Currently unused! Needs more work to reliably resume the pool on reboot,
+ # but only if booting exactly the same image
if ! dmsetup_create_noudevsync "pool-metadata" \
"0 $metadata_dev_sz linear $scratch_device $scratch_device_offset"; then
- echo "$0: Failed to create linear device for pool metadata device."
+ echo "pool: Failed to create linear device for pool metadata device."
else
# Adjust size for pool-data down accordingly
scratch_device_offset="$metadata_dev_sz"
@@ -387,6 +430,7 @@ create_pool() {
fi
if [ -z "$metadata_dev" ]; then
# create RAMdisk in /run for metadata device
+ echo "pool: Creating loopdev in tmpfs for metadata"
mkdir -p /run/openslx
metadata_dev="$( mktemp /run/openslx/.pool-metadata.XXXXXX )"
# Create sparse file of required size
@@ -395,7 +439,7 @@ create_pool() {
declare -r metadata_dev="$( losetup --show --find "$metadata_dev" )"
fi
if [ -z "$metadata_dev" ]; then
- echo "$0: Could not set up persistent or tmpfs-loop metadata device. Aborting."
+ echo "pool: Could not set up persistent or tmpfs-loop metadata device. Aborting."
return 1
fi
@@ -404,21 +448,23 @@ create_pool() {
# No offset, no potential expansion, don't create another linear target
pool_data_dev="$scratch_device"
else
+ echo "pool: Creating additional linear target for data device"
pool_data_dev="/dev/mapper/pool-data"
# Create linear device of the writable device, in case we have an offset from
# the on-disk meta data. Also this way we can easily extend it later.
if ! dmsetup_create_noudevsync "${pool_data_dev##*/}" \
"0 $scratch_device_sz linear $scratch_device $scratch_device_offset"; then
- echo "$0: Failed to create pool data device on '$scratch_device'."
+ echo "pool: Failed to create pool data device on '$scratch_device'."
return 1
fi
fi
local low_water_mark
# Convert MB to blocks
low_water_mark=$(( wanted_low_mb * 2048 / data_block_sz ))
+ echo "pool: Creating thinpool device"
if ! dmsetup_create_noudevsync "${pool_dev##*/}" \
"0 $scratch_device_sz thin-pool $metadata_dev $pool_data_dev $data_block_sz $low_water_mark 1 skip_block_zeroing"; then
- echo "$0: Failed to create thin-pool device (meta: $metadata_dev, data: $pool_data_dev)"
+ echo "pool: Failed to create thin-pool device (meta: $metadata_dev, data: $pool_data_dev)"
return 1
fi
return 0
@@ -427,11 +473,11 @@ create_pool() {
# create_volume <name> <id> <size> [backing_dev]
create_volume() {
if [ -z "$pool_dev" ] || ! [ -b "$pool_dev" ]; then
- echo "$0: Global pool device not set or present."
+ echo "volume: Global pool device not set or present."
return 1
fi
if [ $# -lt 3 ] || [ -z "$1" ]; then
- echo "$0: create_volume: not enough arguments."
+ echo "volume: not enough arguments."
return 1
fi
local name="$1"
@@ -439,12 +485,13 @@ create_volume() {
local size="$3"
local backing_dev="$4" # Optional, internal if empty
+ echo "volume: Creating $id/$name on $pool_dev"
if ! dmsetup message "$pool_dev" 0 "create_thin $id"; then
- echo "$0: Failed to create thin volume with id '$id' in pool '$pool_dev'."
- echo "$0: It might already exists, trying anyway..."
+ echo "volume: Failed to create thin volume with id '$id' in pool '$pool_dev'."
+ echo "volume: It might already exist, trying anyway..."
fi
if ! dmsetup_create_noudevsync "$name" "0 $size thin $pool_dev $id $backing_dev"; then
- echo "$0: Failed to create external snapshot named '$name':"
+ echo "volume: Failed to create external snapshot named '$name':"
echo " Size: $size"
echo " Backing device: $backing_dev"
echo " Thin volume id: $id"
@@ -464,8 +511,9 @@ find_ntfs_partitions() {
[ -z "$SLX_NTFSFREE" ] && return
[ "$SLX_NTFSFREE" = "never" ] && return
[ -e "$ntfs_list" ] && return
+ echo "ntfs: Scanning for suitable NTFS partitions to use as writable device"
if ! command -v ntfsfree &> /dev/null; then
- echo "$0: ntfsfree not found, cannot use NTFS partitions as RW layer"
+ echo "ntfs: ntfsfree not found, cannot use NTFS partitions as RW layer"
return
fi
local part sum ro dev
@@ -480,10 +528,11 @@ find_ntfs_partitions() {
sum="$( ntfsfree --block-size 512 --min-size "$(( 256 * 1024 * 1024 ))" "$part" 2> /dev/null \
| awk -v sum=0 '{if ($1 == "Range") sum += $4}END{printf "%.0f", sum}' )"
# Only consider volume if sum of these ranges > 1GB (this is BLOCKS, not bytes)
- (( "$sum" > 2 * 1024 * 1024 )) || continue
+ (( sum > 2 * 1024 * 1024 )) || continue
echo "$sum $part" # only thing in loop going to stdout
(( ntfs_extra_space_sz += sum ))
done | sort -nr > "$ntfs_list"
+ echo "ntfs: Found $( wc -l < "$ntfs_list" ) suitable partitions"
}
ntfs_extra_space_sz=0
@@ -502,20 +551,25 @@ dev_swap_version &> /dev/null
declare -g id44_crypted=
declare -g writable_device=
if [ -z "$SLX_WRITABLE_DEVICE_IDENTIFIER" ]; then
- SLX_WRITABLE_DEVICE_IDENTIFIER=("44" "87f86132-ff94-4987-b250-444444444444")
- # TODO make scripts reading this variable compatible with list of IDs
- echo "SLX_WRITABLE_DEVICE_IDENTIFIER='${SLX_WRITABLE_DEVICE_IDENTIFIER[0]}'" >> /etc/openslx
- echo "SLX_WRITABLE_DEVICE_IDENTIFIERS='${SLX_WRITABLE_DEVICE_IDENTIFIER[*]}'" >> /etc/openslx
+ SLX_WRITABLE_DEVICE_IDENTIFIER="44 87f86132-ff94-4987-b250-444444444444"
+ echo "SLX_WRITABLE_DEVICE_IDENTIFIER='${SLX_WRITABLE_DEVICE_IDENTIFIER}'" >> /etc/openslx
fi
-# XXX The fuck? This may or may not be an array? Shit will defintely break some day...
+
if [ -n "$SLX_WRITABLE_DEVICE_IDENTIFIER" ]; then
+ unset writable_devices
declare -a writable_devices
- writable_devices=( $( dev_find_partitions "${SLX_WRITABLE_DEVICE_IDENTIFIER[@]}" ) )
+ read -r -a list <<<"$SLX_WRITABLE_DEVICE_IDENTIFIER"
+ echo "Scanning for partitions with type/label ${list[*]}..."
+ while read -r -a list; do
+ writable_devices+=( "${list[@]}" )
+ done < <( dev_find_partitions "${list[@]}" )
+ echo "Found ${#writable_devices[@]} matching partitions"
if [[ "${#writable_devices[@]}" -eq 0 && "$SLX_NTFSFREE" != "never" ]] || [ "$SLX_NTFSFREE" = "always" ]; then
find_ntfs_partitions
fi
if [ -s "$ntfs_list" ] || [[ "${#writable_devices[@]}" -gt 1 ]]; then
# More than one device, and/or NTFS space, need linear
+ echo "Have more than one writable device, creating linear target"
tbl="/run/openslx/dmsetup-linear-id44"
pos=0
grow_max_sz=9999999999
@@ -531,6 +585,7 @@ if [ -n "$SLX_WRITABLE_DEVICE_IDENTIFIER" ]; then
if [ -s "$ntfs_list" ]; then
sum=
while read -r sum dev _ || [ -n "$sum" ]; do # each dev
+ echo "Appending NTFS partition $dev..."
word=
while read -r word range_start_b _ range_sz _ || [ -n "$word" ]; do # each slice of dev
[ "$word" = "Range" ] || continue
@@ -543,7 +598,7 @@ if [ -n "$SLX_WRITABLE_DEVICE_IDENTIFIER" ]; then
# Update counter
(( pos += slice_sz ))
else
- echo "$0: Could not write new table row into $tbl"
+ echo "Could not write new table row into $tbl"
fi
done < <( ntfsfree --block-size 512 --min-size "$(( 256 * 1024 * 1024 ))" "$dev" )
done < "$ntfs_list"
@@ -554,35 +609,35 @@ if [ -n "$SLX_WRITABLE_DEVICE_IDENTIFIER" ]; then
fi
# See if we need a linear target at all
if ! [ -s "$tbl" ]; then
- echo "$0: Empty tmp/id44 table, fallback to RAM"
+ echo "Empty tmp/id44 table, fallback to RAM"
elif [ "$( wc -l < "$tbl" )" -eq 1 ] && [[ "${#writable_devices[@]}" -ge 1 ]]; then
# Only one line, have writable device -> use directly
+ echo "Table somehow ended up with one entry, discarding"
writable_device="${writable_devices[0]}"
else
# set up linera device
+ echo "Setting up linear id44 device with $( wc -l < "$tbl" ) slices"
if ! dmsetup_create_noudevsync "id44-group" < "$tbl"; then
- echo "$0: Error creating group of id44 devices. Fallback to RAM :-("
+ echo "$0: Error creating group of writable devices. Fallback to RAM :-("
else
writable_device="/dev/mapper/id44-group"
fi
fi
else
# Single device
+ echo "Have a single writable device, using it directly"
writable_device="${writable_devices[0]}"
fi
fi
if [ -z "$writable_device" ]; then
- echo "$0: Could not find writable device with id '$SLX_WRITABLE_DEVICE_IDENTIFIER'."
+ echo "Could not find writable device with id(s) '$SLX_WRITABLE_DEVICE_IDENTIFIER'."
ramdisk_fallback
elif is_on "$SLX_ID44_CRYPT"; then
# Config option crypts the entire ID44 device(s), before any slices are taken from it.
if encrypt_device "$writable_device" "id44-crypt"; then
- echo "$0: ID44 encrypted"
writable_device="/dev/mapper/id44-crypt"
# Remember the whole device is already encrypted, and ignore the crypt flag for the partition table later
id44_crypted=1
- else
- echo "$0: Error encrypting ID44 partition"
fi
fi
@@ -598,6 +653,7 @@ fi
# extra swap?
if grep -qFw 'slx.swap' "/proc/cmdline"; then
# Only if our basic writable_device is large enough, or we have ntfs backup
+ echo "Additional swap on ID44 requested if existing is too small"
do_swap_sz=0
if (( writable_device_sz > 80078125 )); then
# more than ~40GB, go ahead
@@ -612,41 +668,36 @@ if grep -qFw 'slx.swap' "/proc/cmdline"; then
# Check how many we have and if they're regular, unencrypted ones.
# If it's plenty, don't cut out swap from our backing device
swap_sz=0
- for part in $( dev_find_partitions "82" "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" ); do
- dev_swap_version "$part" &> /dev/null || continue
- this_sz="$( blockdev --getsz "$part" )"
- (( this_sz > 0 )) && (( swap_sz += this_sz ))
- done
- echo "Have existing swap of $swap_sz blocks"
- # Go ahead with swap? Only if existing swap < 4GB. If so, add line to table.
- if (( do_swap_sz > 0 )) && (( swap_sz < 7812500 )); then
- echo "Adding $do_swap_sz blocks of additional swap on backing dev"
- skb="$(( do_swap_sz / 2 ))"
- SLX_WRITABLE_DEVICE_PARTITION_TABLE="$( printf "%s\n%s" "linear slx-swap ${skb}K 0" \
- "$SLX_WRITABLE_DEVICE_PARTITION_TABLE" )"
+ if (( do_swap_sz == 0 )); then
+ echo "Not enough ID44 space for swap..."
+ else
+ for part in $( dev_find_partitions "82" "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" ); do
+ dev_swap_version "$part" &> /dev/null || continue
+ this_sz="$( blockdev --getsz "$part" )"
+ (( this_sz > 0 )) && (( swap_sz += this_sz ))
+ done
+ echo "Have existing swap of $(( swap_sz / 2 / 1024 ))MiB"
+ (( do_swap_sz -= swap_sz ))
+ # Go ahead with swap? Only if we miss a reasonable amount... ( > 100MiB)
+ if (( do_swap_sz > 204800 )); then
+ echo "Adding $(( do_swap_sz / 2 / 1024 ))MiB of additional swap on backing dev"
+ skb="$(( do_swap_sz / 2 ))"
+ SLX_WRITABLE_DEVICE_PARTITION_TABLE="$( printf "%s\n%s" "linear slx-swap ${skb}K 0" \
+ "$SLX_WRITABLE_DEVICE_PARTITION_TABLE" )"
+ fi
fi
fi
parse_config "$SLX_WRITABLE_DEVICE_PARTITION_TABLE"
# Default to thin-snapshot, if none were configured
-if [ "${#snapshot[@]}" = 0 ] && [ "${#thin_snapshot[@]}" = 0 ]; then
+if [ -z "${snapshot}" ] && [ -z "${thin_snapshot}" ]; then
parse_config "thin-snapshot root 100% 0"
fi
# Sanity checks for weird configurations
-# XXX These were declared array and now turn into strings...
-if [ "${#snapshot[@]}" -gt 1 ]; then
- echo "Multiple snapshots specified, using first one: ${snapshot[0]}"
-fi
-snapshot="${snapshot[0]}"
-if [ "${#thin_snapshot[@]}" -gt 1 ]; then
- echo "Multiple thin-snapshots specified, using first one: ${thin_snapshot[0]}"
-fi
-thin_snapshot="${thin_snapshot[0]}"
if [ -n "$snapshot" ] && [ -n "$thin_snapshot" ]; then
- echo "$0: Both snapshot and thin-snapshot specified, prefering thin-snapshot."
- snapshot=
+ echo "Warning: Both snapshot and thin-snapshot specified, prefering thin-snapshot." >&2
fi
###
@@ -659,7 +710,7 @@ declare -g pool_crypted=
# first, reserve the space for the rootfs cow snapshot (of either type)...
# (this is the first line of our custom partition table)
-read -r name crypt min max ignore <<< "${thin_snapshot:-${snapshot}}"
+read -r name crypt min max _ <<< "${thin_snapshot:-${snapshot}}"
declare -g scratch_device="/dev/mapper/scratch"
declare -gi scratch_device_sz=0
@@ -668,9 +719,9 @@ if (( min <= writable_device_sz )); then
(( scratch_device_sz > writable_device_sz )) && scratch_device_sz="$writable_device_sz"
else
# minimum snapshot size is bigger than physical device size
- echo "$0: Minimum snapshot size is too big for the scratch partition."
- echo "$0: You probably need to use a more conservative value."
- echo "$0: Using this client maximum scratch space ($writable_device_sz sectors)."
+ echo "Warning: Minimum snapshot size is too big for the scratch partition." >&2
+ echo "Warning: You probably need to use a more conservative value." >&2
+ echo "Warning: Using this client maximum scratch space ($writable_device_sz sectors)." >&2
scratch_device_sz="$writable_device_sz"
fi
@@ -678,7 +729,7 @@ if (( scratch_device_sz == writable_device_sz )); then
# Only one, use directly, maybe crypt
if [ -z "$id44_crypted" ] && [ "$crypt" -ne 0 ]; then
if ! encrypt_device "$writable_device" "${scratch_device##*/}" 0 "$scratch_device_sz"; then
- echo "$0: Continuing with unencrypted scratch"
+ echo "Warning: Continuing with unencrypted scratch" >&2
scratch_device="$writable_device"
fi
else
@@ -695,13 +746,13 @@ else
if encrypt_device "$writable_device" "${scratch_device##*/}" 0 "$scratch_device_sz"; then
pool_crypted=1
else
- echo "$0: Continuing with unencrypted scratch"
+ echo "Warning: Continuing with unencrypted scratch" >&2
crypt=0 # So we do the linear thing below
fi
fi
if (( crypt == 0 )) && ! dmsetup_create_noudevsync "${scratch_device##*/}" \
"0 $scratch_device_sz linear $writable_device $writable_device_used_sz"; then
- echo "$0: Failed to create scratch space for the CoW layer."
+ echo "Error: Failed to create scratch space for the CoW layer." >&2
# this should never fail, but if it does, we would likely not be able to use
# $writable_device for any dmsetup stuff, so just fallback to ramdisk
# until we have a better idea on what to do :)
@@ -715,12 +766,13 @@ writable_device_used_sz="$scratch_device_sz"
# setup linear slices of the writable device
for line in "${linear[@]}"; do
[ -z "$line" ] && continue
- read -r name crypt min max ignore <<< "$line"
+ read -r name crypt min max _ <<< "$line"
[ -n "$id44_crypted" ] && crypt=0
+ echo "Creating linear slice '$name'..."
free_space="$(( writable_device_sz - writable_device_used_sz ))"
if [ "$min" -gt "$free_space" ]; then
- echo "$0: Not enough space left for linear devices: '$line' - have $free_space sectors"
- break
+ echo "Error: Not enough space left for linear device $name - have $free_space sectors, need $min" >&2
+ continue
fi
# allocate its max if it fits within the free space, otherwise use the space left.
to_allocate="$max"
@@ -730,12 +782,12 @@ for line in "${linear[@]}"; do
if (( crypt != 0 )) \
&& ! encrypt_device "$writable_device" "${name}" "$writable_device_used_sz" "$to_allocate"; then
- echo "$0: Failed to encrypt '$name', continuing without encryption."
+ echo "Warning: Failed to encrypt '$name', continuing without encryption." >&2
crypt=0
fi
if (( crypt == 0 )) && ! dmsetup_create_noudevsync \
"$name" "0 $to_allocate linear $writable_device $writable_device_used_sz"; then
- echo "$0: Failed to create linear device: $line"
+ echo "Warning: Failed to create linear device: $line" >&2
continue
fi
# TODO sane?
@@ -750,14 +802,19 @@ declare -rg pool_dev="/dev/mapper/pool"
declare -gi root_ntfs_extra=0 # Extra blocks to provision to root fs for later expansion
# Now decide what to do for the writable layer
-if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then
+if [ -n "$thin_snapshot" ] || [ -n "${thin_volume[*]}" ]; then
if ! create_pool ; then
- echo "Failed to create thin pool. Will ignore:"
- echo -e "\tThin snapshot: $(declare -p thin_snapshot)"
- echo -e "\tThin volumes: $(declare -p thin_volume)"
- echo "Trying snapshot fallback..."
- snapshot="$thin_snapshot"
+ {
+ echo "Error: Failed to create thin pool. Will ignore:"
+ echo " Thin snapshot: $(declare -p thin_snapshot)"
+ echo " Thin volumes: $(declare -p thin_volume)"
+ echo "Trying snapshot fallback..."
+ } >&2
+ [ -z "$snapshot" ] && snapshot="$thin_snapshot"
else
+ # Once we have created the pool, there is no point in snapshot fallback,
+ # as the space is already reserved by the pool
+ snapshot=
# the order in which pool devices are created does not matter
# so start with thin volumes starting with id 2 and end with
# the thin-snapshot with id 1 which needs to call finish_setup.
@@ -765,20 +822,22 @@ if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then
# go over thin-volumes
for line in "${thin_volume[@]}"; do
[ -z "$line" ] && continue
- read -r name crypt min max ignore <<< "$line"
+ read -r name crypt min max _ <<< "$line"
if [ -n "$id44_crypted" ] || [ -n "$pool_crypted" ]; then
crypt=0
fi
+ echo "Adding thin volume '$name'..."
# thin-volume can be created with max size,
# since they are overprovisioned anyway.
suffix=
- (( crypt != 0 )) && suffix="-k"
+ (( crypt != 0 )) && suffix="-plain"
if ! create_volume "$name$suffix" "$(( volume_id++ ))" "$max"; then
- echo "Failed to create thin volume '$name'."
+ echo "Error: Failed to create thin volume $name" >&2
+ continue
fi
if (( crypt != 0 )) && ! encrypt_device \
"/dev/mapper/$name$suffix" "$name" 0 "$max"; then
- echo "Failed to encrypt thin volume '$name', continuing without encryption."
+ echo "Warning: Failed to encrypt thin volume '$name', continuing without encryption." >&2
name="$name$suffix"
fi
save_partition_info "$name" "*" "1" "${scratch_device_sz}-${max}"
@@ -787,6 +846,7 @@ if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then
if [ -n "$thin_snapshot" ]; then
# create thin-snapshot, use first one
read -r name _ <<< "$thin_snapshot"
+ echo "Adding base system snapshot '$name'..."
# min/max and crypt was used for the pool data device, ignore it here!
# Calculate how much of the CoW space we reserve for changes in the base
# system. Usually all the files in the base system should be static, but
@@ -808,12 +868,12 @@ if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then
thin_snapshot_sz="$(( thin_snapshot_sz + root_ntfs_extra ))"
fi
if ! create_volume "$name" 1 "$thin_snapshot_sz" "$read_only_device"; then
- echo "Failed to create external snapshot for '$read_only_device'."
- ramdisk_fallback
+ echo "Error: Failed to create external snapshot for '$read_only_device'." >&2
+ ramdisk_fallback # does not return
fi
finish_setup "$name" "1" "$thin_snapshot_sz"
fi
- echo "$0: Thin volumes defined, but no snapshot. Using tmpfs."
+ echo "Warning: Thin volumes defined, but no snapshot. Using tmpfs...." >&2
ramdisk_fallback
fi
fi
@@ -824,9 +884,16 @@ fi
if [ -n "$snapshot" ] && require_exact_scratch_size; then
read -r name crypt min max _ <<< "$snapshot"
[ -n "$id44_crypted" ] && crypt=0
- if create_snapshot "$name N" "$scratch_device"; then
- finish_setup "$name" "1" "$scratch_device_sz"
+ suffix=
+ (( crypt != 0 )) && suffix="-plain"
+ if ! create_snapshot "$name$suffix N" "$scratch_device"; then
+ ramdisk_fallback # no return
+ fi
+ if (( crypt != 0 )) && ! encrypt_device "/dev/mapper/$name$suffix" "$name" 0 "$max"; then
+ echo "Warning: Failed to encrypt snapshot $name, continuing without encryption." >&2
+ name="$name$suffix"
fi
+ finish_setup "$name" "1" "$scratch_device_sz"
fi
# ultimate fallback