summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2020-09-30 16:05:19 +0200
committerSimon Rettberg2020-09-30 16:05:19 +0200
commitf52d4d2b594e61cfd310c11c44e59302c5b97f43 (patch)
tree1a24b5c794f680d35125b288210fb3b6202b2e06
parent[slx-dmsetup] Block zeroing not required in our use case (diff)
downloadsystemd-init-f52d4d2b594e61cfd310c11c44e59302c5b97f43.tar.gz
systemd-init-f52d4d2b594e61cfd310c11c44e59302c5b97f43.tar.xz
systemd-init-f52d4d2b594e61cfd310c11c44e59302c5b97f43.zip
[slx-dmsetup] Add support for ntfsfree
For now, prepare for later on-demand growing of the pool-data davice by using unused space of NTFS partitions. We do this by scanning available NTFS partitions and recording the available free space on them. Additionally, we make the pool-metadata volume a little larger to account for potential future growth of the data part. This feature is controlled by the SLX_NTFSFREE variable which can be empty/"never", "backup" for the scenario described above, or "always" for always using NTFS partition's free space (to be implemented).
-rwxr-xr-xmodules.d/slx-dmsetup/scripts/dmsetup-slx-device58
1 files changed, 56 insertions, 2 deletions
diff --git a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device
index f986f6e9..f9bbdd9d 100755
--- a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device
+++ b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device
@@ -28,6 +28,8 @@ exec &> /run/openslx/dmsetup.log
declare -g read_only_device="$1"
declare -g read_only_device_size="$( blockdev --getsz "$1" )"
+declare -rg ntfs_list="/run/openslx/.thin-ntfs-candidates"
+
# global array variables storing the configuration of the partitions
declare -ag linear snapshot thin_snapshot thin_volume
parse_config() {
@@ -362,11 +364,12 @@ done
writable_device="$scratch_device"
writable_device_size="$scratch_device_size"
-###
+###
## THIN-PROVISIONING
###
declare -rg pool_data_dev="/dev/mapper/pool-data"
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_size=256 # Desired Block size (number of 512byte sectors)
declare -r wanted_low_mb=100 # Free space below this will trigger a dm event
@@ -375,8 +378,29 @@ create_pool() {
modprobe dm-thin-pool || echo "$0: dm-thin-pool load failed, maybe builtin?"
# create temporary metadata device
# calculate number of sectors needed and check boundaries:
- # XXX According to thin-provisioning.txt the / 512 part is WRONG!
+ # XXX Formula from thin-pool.txt calculates size in *bytes*, we want 512b blocks
metadata_dev_size="$(( 48 * writable_device_size / data_block_size / 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
+ # use case this is sensible for now.
+ if [ "$SLX_NTFSFREE" = "backup" ] && (( writable_device_size < 209715200 )) \
+ && [ -z "$metadata_persistent" ]; then
+ find_ntfs_partitions
+ if [ -s "$ntfs_list" ]; then
+ # Look what size we end up if we want at least 50GB
+ local sum="$( awk -v sum=0 \
+ '{sum+=$1; if (sum >= 104857600) exit}END{printf "%.0f", sum}' \
+ "$ntfs_list" )"
+ if (( sum > 0 )); then
+ (( sum > 209715200 )) && sum=209715200 # Max 100GB
+ # Account for this potential growth in the metadata device size for future expansion
+ metadata_dev_size="$(( metadata_dev_size + 48 * sum / data_block_size / 512 ))"
+ echo "$sum" > "/run/openslx/.thin-ntfs-growsize"
+ root_ntfs_extra="$sum"
+ fi
+ fi
+ fi
# Min 2MB -> 4096 sectors, max 16GB -> 33554432 sectors
[ "$metadata_dev_size" -lt 4096 ] && metadata_dev_size="4096"
# TODO handle the exotic case of a too large metadata device to fit within RAM.
@@ -451,6 +475,32 @@ create_volume() {
return 0
}
+# Find NTFS partitions with decently sized ranges of
+# free space. We can use these as our writable layer
+# for our thin-pool, if configured.
+# If suitable, this will create the file $ntfs_list with
+# one line per suitable partition, format
+# total_size_blocks devpath
+# Results are sorted by size, descending order
+find_ntfs_partitions() {
+ [ -z "$SLX_NTFSFREE" ] && return
+ [ "$SLX_NTFSFREE" = "never" ] && return
+ [ -e "$ntfs_list" ] && return
+ if ! command -v ntfsfree &> /dev/null; then
+ echo "$0: ntfsfree not found, cannot use NTFS partitions as RW layer"
+ return
+ fi
+ local part sum
+ for part in /dev/disk/by-partuuid/*; do
+ # Only count ranges >= 256MB, sum will be in number of 512b blocks
+ sum="$( ntfsfree --block-size 512 --min-size "$(( 256 * 1024 * 1024 ))" "$part" \
+ | 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
+ echo "$sum $part" # only thing in loop going to stdout
+ done | sort -nr > "$ntfs_list"
+}
+
# Now decide what to do for the writable layer
if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then
@@ -495,6 +545,10 @@ if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then
else
thin_snapshot_size="$read_only_device_size"
fi
+ # For later on-demand growing
+ if (( root_ntfs_extra > 0 )); then
+ thin_snapshot_size="$(( thin_snapshot_size + root_ntfs_extra ))"
+ fi
if ! create_volume "$name" 1 "$thin_snapshot_size" "$read_only_device"; then
echo "Failed to create external snapshot for '$read_only_device'."
ramdisk_fallback