summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2022-05-23 12:16:43 +0200
committerSimon Rettberg2022-05-23 12:16:43 +0200
commit5de6edcdad87ad717129462b0fe89c47e6f3b288 (patch)
treeed73d2cdb82bb1d287706e1ac111dea383d8786e
parentSplit initramfs copying logic into new module, enable in debug mode only (diff)
downloadsystemd-init-5de6edcdad87ad717129462b0fe89c47e6f3b288.tar.gz
systemd-init-5de6edcdad87ad717129462b0fe89c47e6f3b288.tar.xz
systemd-init-5de6edcdad87ad717129462b0fe89c47e6f3b288.zip
[slx-dmsetup] linear ID44 target; support SLX_NTFSFREE = "always"
-rwxr-xr-xmodules.d/slx-dmsetup/scripts/dmsetup-slx-device323
1 files changed, 193 insertions, 130 deletions
diff --git a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device
index 8856a10e..f2977b9e 100755
--- a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device
+++ b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device
@@ -121,11 +121,16 @@ parse_config() {
# Helper to call 'dmsetup setup' without syncing with udev
# and then actively create the devices with the mknodes command.
-# dmsetup_create_noudevsync <name> <table>
+# Either pass the table contents as $2, or pipe them into the function
+# dmsetup_create_noudevsync <name> [table]
dmsetup_create_noudevsync() {
(
set -o errexit
- printf "%s\n" "$2" | dmsetup create "$1" --noudevsync
+ if [ -n "$2" ]; then
+ printf "%s\n" "$2" | dmsetup create "$1" --noudevsync
+ else
+ dmsetup create "$1" --noudevsync
+ fi
dmsetup mknodes --noudevsync "$1"
)
local ret=$?
@@ -182,7 +187,8 @@ ramdisk_fallback() {
"0 $read_only_device_sz linear $read_only_device 0
$read_only_device_sz $ram_cow_sz zero"
)
- if [ "$?" -eq 0 ]; then
+ local ret="$?"
+ if [ "$ret" -eq 0 ]; then
read_only_device="$extended_device"
read_only_device_sz="$(( read_only_device_sz + ram_cow_sz ))"
else
@@ -262,128 +268,6 @@ save_partition_info() {
echo "/dev/mapper/$1 $2 ${opts}" >> "$partitions_config"
}
-###
-## MAIN
-###
-
-. /etc/openslx
-# This is the main variable driving this script
-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
-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
- # only first one for now TODO create linear devices of all ID44s
- writable_device="$(slx-tools dev_find_partitions "${SLX_WRITABLE_DEVICE_IDENTIFIER[@]}" | head -n 1)"
-fi
-if [ -z "$writable_device" ]; then
- echo "$0: Could not find writable device with id '$SLX_WRITABLE_DEVICE_IDENTIFIER'."
- ramdisk_fallback
-fi
-
-# NOTE: from here on out, every value related to size is in 512 bytes sectors!
-declare -rg writable_device_sz="$( blockdev --getsz "$writable_device" )"
-
-# If SLX_WRITABLE_DEVICE_PARTITION_TABLE is not set, just do
-# regular thin-snapshot for the CoW layer, else parse it.
-if [ -n "$SLX_WRITABLE_DEVICE_PARTITION_TABLE" ]; then
- parse_config "$SLX_WRITABLE_DEVICE_PARTITION_TABLE"
-fi
-# Default to thin-snapshot, if none were configured
-if [ "${#snapshot[@]}" = 0 ] && [ "${#thin_snapshot[@]}" = 0 ]; 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=
-fi
-
-###
-## LINEAR SLICES
-###
-
-# start allocating spaces to the configured devices
-declare -g writable_device_used_sz=0
-
-# first, reserve the space for the rootfs cow snapshot (of either type)...
-read -r name crypt min max ignore <<< "${thin_snapshot:-${snapshot}}"
-
-declare -g scratch_device="/dev/mapper/scratch"
-declare -gi scratch_device_sz=0
-if (( min <= writable_device_sz )); then
- scratch_device_sz="$max"
- (( 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)."
- scratch_device_sz="$writable_device_sz"
-fi
-
-# Create a linear target for the scratch device. This might seem superfluous,
-# but it works around problems when using NVMe as pool data device directly.
-if ! 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."
- # 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 :)
- ramdisk_fallback
-fi
-save_partition_info "${scratch_device##*/}" "*" "1" "$scratch_device_sz"
-
-# encrypt the scratch device, if configured
-if [ "$crypt" -ne 0 ] && encrypt_device \
- "$scratch_device" "${scratch_device##*/}-crypt" "$scratch_device_sz"; then
- scratch_device="/dev/mapper/${scratch_device##*/}-crypt"
-else
- echo "$0: Continuing with unencrypted scratch"
-fi
-
-writable_device_used_sz="$scratch_device_sz"
-
-# first setup linear slices of the writable device
-for line in "${linear[@]}"; do
- [ -z "$line" ] && continue
- read -r name crypt min max ignore <<< "$line"
- 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'"
- break
- fi
- # allocate its max if it fits within the free space, otherwise use the space left.
- to_allocate="$max"
- [ "$to_allocate" -gt "$free_space" ] && to_allocate="$free_space"
-
- if ! dmsetup_create_noudevsync "$name" "0 $to_allocate linear $writable_device $writable_device_used_sz"; then
- echo "$0: Failed to create linear device: $line"
- continue
- fi
- # TODO sane?
- save_partition_info "$name" "*" "1" "$to_allocate"
- if [ "$crypt" -ne 0 ] && \
- ! encrypt_device "/dev/mapper/$name" "${name}-crypt" "$to_allocate"; then
- echo "$0: Failed to encrypt '$name'."
- fi
- writable_device_used_sz=$(( to_allocate + writable_device_used_sz ))
-done
-
# This will create another dm-linear on top of $scratch_device in case its
# size differs from $scratch_device_sz. This is useful for setups where you
# cannot explicitly configure how much space to use from the underlying device,
@@ -408,11 +292,6 @@ require_exact_scratch_size() {
return 0
}
-###
-## THIN-PROVISIONING
-###
-declare -rg pool_dev="/dev/mapper/pool"
-declare -gi root_ntfs_extra=0 # Extra blocks to provision to root fs for later expansion
create_pool() {
declare -r data_block_sz=256 # Desired Block size (number of 512byte sectors)
declare -r wanted_low_mb=100 # Free space below this will trigger a dm event
@@ -559,6 +438,190 @@ find_ntfs_partitions() {
done | sort -nr > "$ntfs_list"
}
+###
+## MAIN
+###
+
+. /etc/openslx
+# This is the main variable driving this script
+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
+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
+ # only first one for now TODO create linear devices of all ID44s
+ declare -a writable_devices
+ writable_devices=( $( slx-tools dev_find_partitions "${SLX_WRITABLE_DEVICE_IDENTIFIER[@]}" ) )
+ 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
+ SLX_NTFSFREE="never" # Don't try to add NTFS space later
+ tbl="/run/openslx/dmsetup-linear-id44"
+ pos=0
+ grow_max_sz=9999999999
+ for dev in "${writable_devices[@]}"; do
+ max="$(( grow_max_sz - pos ))"
+ (( max <= 0 )) && break
+ sz="$( blockdev --getsz "$dev" )"
+ (( sz > 0 )) || continue
+ (( sz > max )) && sz="$max"
+ echo "$pos $sz linear $dev 0"
+ (( pos += sz ))
+ done > "$tbl"
+ if [ -s "$ntfs_list" ]; then
+ sum=
+ while read -r sum dev _ || [ -n "$sum" ]; do # each dev
+ word=
+ while read -r word range_start_b _ range_sz _ || [ -n "$word" ]; do # each slice of dev
+ [ "$word" = "Range" ] || continue
+ (( range_sz > 0 )) || continue
+ slice_sz="$(( grow_max_sz - pos ))"
+ (( slice_sz <= 0 )) && break
+ (( slice_sz > range_sz )) && slice_sz="$range_sz"
+ # Append line
+ if echo "$pos $slice_sz linear $dev $range_start_b" >> "$tbl"; then
+ # Update counter
+ (( pos += slice_sz ))
+ else
+ echo "$0: Could not write new table row into $tbl"
+ fi
+ done < <( ntfsfree --block-size 512 --min-size "$(( 256 * 1024 * 1024 ))" "$dev" )
+ done < "$ntfs_list"
+ fi
+ # See if we need a linear target at all
+ if ! [ -s "$tbl" ]; then
+ echo "$0: 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
+ writable_device="${writable_devices[0]}"
+ else
+ # set up linera device
+ if ! dmsetup_create_noudevsync "id44-group" < "$tbl"; then
+ echo "$0: Error creating group of id44 devices. Fallback to RAM :-("
+ else
+ writable_device="/dev/mapper/id44-group"
+ fi
+ fi
+ else
+ # Single device
+ 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'."
+ ramdisk_fallback
+fi
+
+# NOTE: from here on out, every value related to size is in 512 bytes sectors!
+declare -rg writable_device_sz="$( blockdev --getsz "$writable_device" )"
+
+# If SLX_WRITABLE_DEVICE_PARTITION_TABLE is not set, just do
+# regular thin-snapshot for the CoW layer, else parse it.
+if [ -n "$SLX_WRITABLE_DEVICE_PARTITION_TABLE" ]; then
+ parse_config "$SLX_WRITABLE_DEVICE_PARTITION_TABLE"
+fi
+# Default to thin-snapshot, if none were configured
+if [ "${#snapshot[@]}" = 0 ] && [ "${#thin_snapshot[@]}" = 0 ]; 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=
+fi
+
+###
+## LINEAR SLICES
+###
+
+# start allocating spaces to the configured devices
+declare -g writable_device_used_sz=0
+
+# first, reserve the space for the rootfs cow snapshot (of either type)...
+read -r name crypt min max ignore <<< "${thin_snapshot:-${snapshot}}"
+
+declare -g scratch_device="/dev/mapper/scratch"
+declare -gi scratch_device_sz=0
+if (( min <= writable_device_sz )); then
+ scratch_device_sz="$max"
+ (( 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)."
+ scratch_device_sz="$writable_device_sz"
+fi
+
+# Create a linear target for the scratch device. This might seem superfluous,
+# but it works around problems when using NVMe as pool data device directly.
+if ! 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."
+ # 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 :)
+ ramdisk_fallback
+fi
+save_partition_info "${scratch_device##*/}" "*" "1" "$scratch_device_sz"
+
+# encrypt the scratch device, if configured
+if [ "$crypt" -ne 0 ] && encrypt_device \
+ "$scratch_device" "${scratch_device##*/}-crypt" "$scratch_device_sz"; then
+ scratch_device="/dev/mapper/${scratch_device##*/}-crypt"
+else
+ echo "$0: Continuing with unencrypted scratch"
+fi
+
+writable_device_used_sz="$scratch_device_sz"
+
+# first setup linear slices of the writable device
+for line in "${linear[@]}"; do
+ [ -z "$line" ] && continue
+ read -r name crypt min max ignore <<< "$line"
+ 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'"
+ break
+ fi
+ # allocate its max if it fits within the free space, otherwise use the space left.
+ to_allocate="$max"
+ [ "$to_allocate" -gt "$free_space" ] && to_allocate="$free_space"
+
+ if ! dmsetup_create_noudevsync "$name" "0 $to_allocate linear $writable_device $writable_device_used_sz"; then
+ echo "$0: Failed to create linear device: $line"
+ continue
+ fi
+ # TODO sane?
+ save_partition_info "$name" "*" "1" "$to_allocate"
+ if [ "$crypt" -ne 0 ] && \
+ ! encrypt_device "/dev/mapper/$name" "${name}-crypt" "$to_allocate"; then
+ echo "$0: Failed to encrypt '$name'."
+ fi
+ writable_device_used_sz=$(( to_allocate + writable_device_used_sz ))
+done
+
+###
+## THIN-PROVISIONING
+###
+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