From 2c9e3cf746d577d3d66245cf1753887c3ccb8244 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 2 Oct 2020 11:07:39 +0200 Subject: [slx-dmsetup] part-table: Allow different units for min and max It can useful to specify a minumum size in absolute terms, but have the maximum value be a percentage of the writable device. --- modules.d/slx-dmsetup/scripts/dmsetup-slx-device | 83 +++++++++++++++--------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device index ff25e167..dffc203c 100755 --- a/modules.d/slx-dmsetup/scripts/dmsetup-slx-device +++ b/modules.d/slx-dmsetup/scripts/dmsetup-slx-device @@ -32,6 +32,31 @@ declare -g read_only_device_sz="$( blockdev --getsz "$1" )" declare -rg ntfs_list="/run/openslx/.thin-ntfs-candidates" +# handle_unit +# Supply percentage, or size in [kmgt]bytes, +# returns appropriate value in number of 512b sectors +handle_unit() { + # default to bytes + local -i potency=0 + local -i val="$1" + case "$2" in + [%]) # These are relative to the writable CoW device + # Allow > 100% for over-provisioning + val="$(( writable_device_sz * val / 100 ))" + ;; + [Kk]) potency=1 ;;& + [Mm]) potency=2 ;;& + [Gg]) potency=3 ;;& + [Tt]) potency=4 ;;& + *) + # => 1024 ** potency for G, M, K, etc results in bytes + # => bytes / 512 = sectors + val=$(( val * ( 1024 ** potency) / 512 )) + ;; + esac + echo "$val" +} + # global array variables storing the configuration of the partitions declare -ag linear snapshot thin_snapshot thin_volume parse_config() { @@ -49,42 +74,36 @@ parse_config() { echo "$0: Ignoring nameless entry: $line" continue fi - unset unit min max - # ranges can be like: 40G, 40-80G, 10-20% - if ! [[ $range =~ ^([0-9]+-)*([0-9])+[GgMmKkBb%]$ ]]; then + unset min_unit max_unit min max + # ranges can be like: 40G, 40-80G, 10G-20% + if ! [[ "$range" =~ ^([0-9]+)([GgMmKkBb%]?)(-([0-9]+)([GgMmKkBb%]?))?$ ]]; then echo "$0: Ignoring invalid range: $line" continue fi - # process ranges: convert percentages (of read_only_device!) - # to actual sizes (in sectors!) before saving them - local unit=${range: -1} - local min="$(cut -d'-' -f1 <<< "${range%?}" )" - local max="$(cut -d'-' -f2 <<< "${range%?}" )" - if [ "$min" -gt "$max" ]; then - echo "$0: Ignoring invalid range: $line" - continue + local min="${BASH_REMATCH[1]}" + local max="${BASH_REMATCH[4]:-${BASH_REMATCH[1]}}" + local min_unit="${BASH_REMATCH[2]:-${BASH_REMATCH[5]}}" + local max_unit="${BASH_REMATCH[5]:-${BASH_REMATCH[2]}}" + if [ -z "$min_unit" ]; then + echo "$0: WARNING: No unit given in range, assuming BYTES: $line" + fi + min="$( handle_unit "$min" "$min_unit" )" + max="$( handle_unit "$max" "$max_unit" )" + if (( min > max )); then + # So, we might end up with something like 30G-100%, but the writable device + # is only 20GB. In that case we most likely want to contine, and not consider + # this an error. So let's try to come up with some logic on what is an error + # and what isn't. Probably anything involving a mix of percentage and + # non-percentage should not be an error. + if [[ "$min_unit" = "%" && "$max_unit" != "%" ]] \ + || [[ "$min_unit" != "%" && "$max_unit" = "%" ]]; then + # Let's hope for the best + max="$min" + else + echo "$0: Ignoring invalid range (min > max): $line" + continue + fi fi - # default for bytes - local -i potency=0 - case "$unit" in - [%]) - if [ "$max" -gt 100 ]; then - echo "Ignoring invalid percentages: $min/$max" - continue - fi - min=$(( writable_device_sz * min / 100 )) - max=$(( writable_device_sz * max / 100 )) - ;; - [Kk]) potency=1 ;;& - [Mm]) potency=2 ;;& - [Gg]) potency=3 ;;& - *) - # => 1024 ** potency for G, M, K, etc results in bytes - # => bytes / 512 = sectors - min=$(( min * ( 1024 ** potency) / 512 )) - max=$(( max * ( 1024 ** potency) / 512 )) - ;; - esac if ! [[ "$crypt" =~ ^[01]$ ]]; then echo "$0: Disabling encryption due to invalid crypt argument: $line" crypt=0 -- cgit v1.2.3-55-g7522