diff options
author | Jonathan Bauer | 2020-05-25 11:26:54 +0200 |
---|---|---|
committer | Jonathan Bauer | 2020-05-25 11:26:54 +0200 |
commit | 8b36285c9ec75ee9fa59f44b0714b952b574190f (patch) | |
tree | 3d4e51530e54e3d7643e47f2bd4e550be0de07f0 /modules.d/slx-dmsetup | |
parent | build-initramfs.sh: support CentOS-7 again (diff) | |
parent | Merge branch 'master' into nobash-merge (diff) | |
download | systemd-init-8b36285c9ec75ee9fa59f44b0714b952b574190f.tar.gz systemd-init-8b36285c9ec75ee9fa59f44b0714b952b574190f.tar.xz systemd-init-8b36285c9ec75ee9fa59f44b0714b952b574190f.zip |
Merge branch 'nobash-merge' into downloader-nobash-merge
Diffstat (limited to 'modules.d/slx-dmsetup')
-rwxr-xr-x | modules.d/slx-dmsetup/module-setup.sh | 5 | ||||
-rwxr-xr-x | modules.d/slx-dmsetup/scripts/dmsetup-slx-device | 73 | ||||
-rw-r--r-- | modules.d/slx-dmsetup/scripts/gen-fstab-persistent | 52 | ||||
-rw-r--r-- | modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh | 52 | ||||
-rwxr-xr-x | modules.d/slx-dmsetup/scripts/get-partitions-by-id | 60 |
5 files changed, 62 insertions, 180 deletions
diff --git a/modules.d/slx-dmsetup/module-setup.sh b/modules.d/slx-dmsetup/module-setup.sh index 68e9b7b4..dff4e34b 100755 --- a/modules.d/slx-dmsetup/module-setup.sh +++ b/modules.d/slx-dmsetup/module-setup.sh @@ -11,14 +11,15 @@ 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 \ + mkfs.xfs \ xfs_repair xfs_growfs } installkernel() { # install those modules in case the used kernel does not have them builtin instmods \ - dm-thin-pool dm-snapshot \ + dm-thin-pool dm-snapshot dm-zero \ dm-crypt crc32c xts \ xfs ext4 } diff --git a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device index 36dfef10..6ee810c4 100755 --- a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device +++ b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device @@ -24,8 +24,8 @@ exec &> /run/openslx/dmsetup.log # read-only device to prepare for CoW [ -z "$1" ] && emergency_shell "Read-only device was not given!" -declare -rg read_only_device="$1" -declare -rg read_only_device_size="$(blockdev --getsz $1)" +declare -g read_only_device="$1" +declare -g read_only_device_size="$(blockdev --getsz $1)" # global array variables storing the configuration of the partitions declare -ag linear snapshot thin_snapshot thin_volume @@ -95,7 +95,7 @@ parse_config() { dmsetup_create_noudevsync() { ( set -o errexit - dmsetup create "$1" --noudevsync --table "$2" + printf "%s\n" "$2" | dmsetup create "$1" --noudevsync dmsetup mknodes --noudevsync "$1" ) local ret=$? @@ -129,24 +129,63 @@ create_snapshot() { return 0 } -# Call this to fallback to a RAMdisk stored under /run/openslx -# This will call terminate the whole script by calling finish_setup, if successful +# This function is called if no ID44 partition could be found or anoother kind +# of critical error occurs during the CoW layer setup. It will combine the +# the read-only device with a DM zero device to increase its virtual size +# by half the RAM size. A sparse file of that size will then be created and +# placed on a dedicated tmpfs. 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 - writable_device="$(losetup --show --find "$file")" - cow_device_candidate="root" + + # RAM size in kb, note that this is equal to half + # of the entire RAM in 512-bytes sectors. + local ram_size_in_kb="$(awk '/MemTotal/ {printf("%d\n", $2 )}' /proc/meminfo)" + + # 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 zero "0 $ram_size_in_kb zero" + dmsetup_create_noudevsync "${extended_device##*/}" \ + "0 $read_only_device_size linear $read_only_device 0 + $read_only_device_size $ram_size_in_kb linear /dev/mapper/zero 0" + ) + if [ "$?" -eq 0 ]; then + read_only_device="$extended_device" + read_only_device_size="$(( read_only_device_size + ram_size_in_kb ))" + else + echo "$0: Failed to setup the fake larger '$read_only_device'." + echo "$0: Continuing with its original size." + fi + + # prepare dedicated tmpfs mount point + local cow_tmpfs="/run/openslx/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 + if ! mount -t tmpfs cow-tmpfs -o size="$(( read_only_device_size / 2 ))k" "$cow_tmpfs"; then + echo "$0: Failed to mount tmpfs in '$cow_tmpfs' of size '$(( read_only_device_size / 2 ))'." + fi + + # create sparse file there + local file="$(mktemp -u -p "$cow_tmpfs" dnbd_cow.XXX)" + if ! dd of="$file" seek="$(( read_only_device_size / 2 ))" bs=1k count=0 &> /dev/null; then + emergency_shell "Failed to allocate CoW file $file." + fi + declare -rg writable_device="$(losetup --show --find "$file")" + local cow_device_candidate="root" while [ -b "/dev/mapper/$cow_device_candidate" ]; do cow_device_candidate="root.$RANDOM" done if [ -z "$writable_device" ] || ! create_snapshot "$cow_device_candidate N"; then emergency_shell "CRITICAL: failed to setup RAMdisk fallback." - exit 1 fi - finish_setup "$cow_device_candidate" "0" "$size" + finish_setup "$cow_device_candidate" "0" "$read_only_device_size" } # finish_setup <device> <type> [<size>] @@ -200,9 +239,15 @@ save_partition_info() { . /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 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)" + 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'." diff --git a/modules.d/slx-dmsetup/scripts/gen-fstab-persistent b/modules.d/slx-dmsetup/scripts/gen-fstab-persistent deleted file mode 100644 index ed00b5de..00000000 --- a/modules.d/slx-dmsetup/scripts/gen-fstab-persistent +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -# -# Hook to generate stage4's fstab entries for persistent partitions -# -# Persistent identifiers (MBR types, GPT partition labels) -# are expected to be specified in the OpenSLX config -# as 'SLX_PERSISTENT_DEVICE_IDENTIFIER' and their filesystem -# as 'SLX_PERSISTENT_DEVICE_FILESYSTEM', e.g ext4 or xfs. -# If not specified, will default to 'auto' but will not -# active systemd's features 'x-systemd.makefs' and 'x-systemd.growfs' - -. /etc/openslx - -type -p emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh - -# NOTE: systemd makes the mount point path automatically. -# if multiple exists, take the biggest one (first in the list) -if [ -n "$SLX_PERSISTENT_DEVICE_IDENTIFIER" ]; then - declare -a persistent_dev_list - for persistent_dev in \ - $(get_partitions_by_id ${SLX_PERSISTENT_DEVICE_IDENTIFIER//,/ /}); do - [ -z "$persistent_dev" ] && continue - persistent_dev_list+=("$persistent_dev") - done - if [ "${#persistent_dev[@]}" -gt 0 ]; then - if [ "${#persistent_dev[@]}" -gt 1 ]; then - warn "$0: More than one persistent device found." - warn "$0: Will use the biggest one: ${persistent_dev[0]}" - fi - persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" - persistent_mount_opts="nofail" - if [ -n "$SLX_PERSISTENT_DEVICE_FILESYSTEM" ]; then - #persistent_mount_opts+=",x-systemd.requires=ensure-fs@${persistent_dev_systemd_name}" - persistent_mount_opts+=",x-systemd.after=ensure-fs@${persistent_dev_systemd_name}" - fi - ( - echo -ne "${persistent_dev[0]}\t" - echo -ne "${SLX_PERSISTENT_DEVICE_MOUNT_POINT:-/opt/openslx/persistent}\t" - echo -ne "${SLX_PERSISTENT_DEVICE_FILESYSTEM:-auto}\t" - echo -ne "${persistent_mount_opts}\t0\t2" - ) >> "$NEWROOT/etc/fstab" - - # drop-in to create filesystem if needed and - #persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" - #mkdir -p "$NEWROOT/etc/systemd/system/${persistent_dev_systemd_name}" - #cat <<- EOF > "$NEWROOT" - #EOF - else - warn "$0: No device with ID '$SLX_PERSISTENT_DEVICE_IDENTIFIER' found." - fi -fi -true diff --git a/modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh b/modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh deleted file mode 100644 index 5c6f2b82..00000000 --- a/modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -# -# Hook to generate stage4's fstab entries for persistent partitions -# -# Persistent identifiers (MBR types, GPT partition labels) -# are expected to be specified in the OpenSLX config -# as 'SLX_PERSISTENT_DEVICE_IDENTIFIER' and their filesystem -# as 'SLX_PERSISTENT_DEVICE_FILESYSTEM', e.g ext4 or xfs. -# If not specified, will default to 'auto' but will not -# active systemd's features 'x-systemd.makefs' and 'x-systemd.growfs' - -. /etc/openslx - -type -p emergency_shell >/dev/null 2>&1 || source /lib/dracut-lib.sh - -# NOTE: systemd makes the mount point path automatically. -# if multiple exists, take the biggest one (first in the list) -if [ -n "$SLX_PERSISTENT_DEVICE_IDENTIFIER" ]; then - declare -a persistent_dev_list - for persistent_dev in \ - $(get-partitions-by-id ${SLX_PERSISTENT_DEVICE_IDENTIFIER//,/ /}); do - [ -z "$persistent_dev" ] && continue - persistent_dev_list+=("$persistent_dev") - done - if [ "${#persistent_dev[@]}" -gt 0 ]; then - if [ "${#persistent_dev[@]}" -gt 1 ]; then - warn "$0: More than one persistent device found." - warn "$0: Will use the biggest one: ${persistent_dev[0]}" - fi - persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" - persistent_mount_opts="nofail" - if [ -n "$SLX_PERSISTENT_DEVICE_FILESYSTEM" ]; then - #persistent_mount_opts+=",x-systemd.requires=ensure-fs@${persistent_dev_systemd_name}" - persistent_mount_opts+=",x-systemd.after=ensure-fs@${persistent_dev_systemd_name}" - fi - ( - echo -ne "${persistent_dev[0]}\t" - echo -ne "${SLX_PERSISTENT_DEVICE_MOUNT_POINT:-/opt/openslx/persistent}\t" - echo -ne "${SLX_PERSISTENT_DEVICE_FILESYSTEM:-auto}\t" - echo -ne "${persistent_mount_opts}\t0\t2" - ) >> "$NEWROOT/etc/fstab" - - # drop-in to create filesystem if needed and - #persistent_dev_systemd_name="$( tr '/' '-' <<< ${persistent_dev[0]:1})" - #mkdir -p "$NEWROOT/etc/systemd/system/${persistent_dev_systemd_name}" - #cat <<- EOF > "$NEWROOT" - #EOF - else - warn "$0: No device with ID '$SLX_PERSISTENT_DEVICE_IDENTIFIER' found." - fi -fi -true diff --git a/modules.d/slx-dmsetup/scripts/get-partitions-by-id b/modules.d/slx-dmsetup/scripts/get-partitions-by-id deleted file mode 100755 index 2fe5ce7a..00000000 --- a/modules.d/slx-dmsetup/scripts/get-partitions-by-id +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash -# -# Get all partitions with given ids (list of /dev/sdXX) -# Examples of supported ID types: -# * MBR's type: 44 -# * GPT's UUID: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f (swap) -# * GPT's Name: OpenSLX-ID44 -# -# First argument can be a block device to limit the search to -# partitions thereof, e.g. for /dev/loop0 to look for /dev/loop0pX -# -# NOTE: for compatibility reasons, MBR's type will also -# be matched against part name 'OpenSLX-ID<id>'. -# The output will be a list of matching devices, -# sorted from largest to smallest. -get_partitions_by_id () { - local ID dev exp target - exp= - # target for the scan, defaults to /dev to check everything - target=/dev - if [ -b "$1" ]; then - target="$1"'*' - shift - fi - # support commas and pipes to separate identifiers - local args=$@ - set -- ${args//[,|]/ } - while [ $# -gt 0 ]; do - ID=$1 - shift - [ -z "$ID" ] && continue - # if single digit, e.g. 7, look for 0x7 and 0x07 - [[ $ID =~ ^[0-9]$ ]] && ID="0?$ID" - if [[ $ID =~ ^[0-9]{2}$ ]]; then - # if double digit look for MBR types and OpenSLX-ID$ID GPT labels - exp="$exp|ID_PART_ENTRY_(NAME=OpenSLX-ID|TYPE=0x)$ID" - elif [[ $ID =~ ^(0x[0-9]{2}|[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})$ ]]; then - # if full MBR type (e.g. 0x44) or UUID look for TYPE - exp="$exp|ID_PART_ENTRY_TYPE=$ID" - else - # something else, look for names of partitions / filesystems - exp="$exp|ID_(PART_ENTRY_NAME|FS_LABEL)=$ID" - fi - done - exp=${exp:1} - #echo "Partition find is '$exp'" >&2 - for dev in $(find $target -type b); do - udevadm info --name="$dev" | grep -iqE "($exp)\$" \ - && echo "$(blockdev --getsize64 "$dev") $dev" - done | sort -n -k1 -r | cut -d' ' -f2 -} - -## MAIN -if [ $# -eq 0 ]; then - echo "$0 needs at least one argument." - exit 1 -fi - -get_partitions_by_id $@ - |