summaryrefslogtreecommitdiffstats
path: root/modules.d/slx-dmsetup
diff options
context:
space:
mode:
authorJonathan Bauer2020-05-25 11:26:54 +0200
committerJonathan Bauer2020-05-25 11:26:54 +0200
commit8b36285c9ec75ee9fa59f44b0714b952b574190f (patch)
tree3d4e51530e54e3d7643e47f2bd4e550be0de07f0 /modules.d/slx-dmsetup
parentbuild-initramfs.sh: support CentOS-7 again (diff)
parentMerge branch 'master' into nobash-merge (diff)
downloadsystemd-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-xmodules.d/slx-dmsetup/module-setup.sh5
-rwxr-xr-xmodules.d/slx-dmsetup/scripts/dmsetup-slx-device73
-rw-r--r--modules.d/slx-dmsetup/scripts/gen-fstab-persistent52
-rw-r--r--modules.d/slx-dmsetup/scripts/generate-fstab-persistent.sh52
-rwxr-xr-xmodules.d/slx-dmsetup/scripts/get-partitions-by-id60
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 $@
-