From af38c279daaea45fcb35ab5370c2b8032e2cf5f4 Mon Sep 17 00:00:00 2001 From: Chris Hammer Date: Mon, 14 Oct 2024 14:24:28 -0400 Subject: [PATCH] add pvsqueeze.sh script, and execute it prior to ALL bigboot executions --- bigboot_execute_resize.yml | 16 ++++++--- scripts/pvsqueeze.sh | 68 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 scripts/pvsqueeze.sh diff --git a/bigboot_execute_resize.yml b/bigboot_execute_resize.yml index 3f2c3b1..1274d3a 100644 --- a/bigboot_execute_resize.yml +++ b/bigboot_execute_resize.yml @@ -31,13 +31,19 @@ when: - bigboot_data[inventory_hostname]['bigboot_execute_shrink_lv'] | default(false) | bool - - name: Expand the /boot partition as requested - ansible.builtin.import_role: - name: infra.lvm_snapshots.bigboot - vars: - bigboot_partition_size: "{{ bigboot_size_target }}" + - name: Shift free extents and expand /boot when: - bigboot_data[inventory_hostname]['bigboot_execute_bigboot'] | bool + block: + - name: Shift free extents to end of PV + ansible.builtin.script: "scripts/pvsqueeze.sh {{ bigboot_data[inventory_hostname]['bigboot_pv'] }}" + register: bigboot_pvsqueeze + + - name: Expand the /boot partition as requested + ansible.builtin.import_role: + name: infra.lvm_snapshots.bigboot + vars: + bigboot_partition_size: "{{ bigboot_size_target }}" - name: Restore service state for disabled services ansible.builtin.import_tasks: tasks/restore_services.yml diff --git a/scripts/pvsqueeze.sh b/scripts/pvsqueeze.sh new file mode 100644 index 0000000..05b762a --- /dev/null +++ b/scripts/pvsqueeze.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# +# pvsqueeze - Squeeze PEs into free holes +# +# This script iteratively moves linear (allocated to LV) PEs to fill in free +# holes found in a PV segement map. The end result is that all free PEs are +# at the end of the PV. Use this script as required in anger! +# + +# Usage +if [[ ! $1 =~ ^/dev/ ]]; then + echo "Usage: $0 PV" + exit 1 +fi + +# Set some vars +pvdev=$1 +pvsargs='--noheadings --nameprefixes --segments -o pvseg_start,pvseg_size,segtype' + +# Show current segment map +echo 'PV segment map before squeeze:' +pvs "$pvdev" --segments -o lvname,pvseg_start,pvseg_size,seg_le_ranges +if [[ $? -ne 0 ]]; then + echo "$0: Fatal error getting PV info" + exit 1 +fi + +# Iterate stuffing PEs in each free hole +while true; do + # Find first free segment + LVM2_PVSEG_START= + eval $(pvs "$pvdev" $pvsargs | grep SEGTYPE=.free. | head -1) + if [[ -z $LVM2_PVSEG_START ]]; then + echo "$0: No free segments found" + exit 1 + fi + free_start=$LVM2_PVSEG_START + free_size=$LVM2_PVSEG_SIZE + + # Find the last linear segment + LVM2_PVSEG_START= + eval $(pvs "$pvdev" $pvsargs | grep SEGTYPE=.linear. | tail -1) + if [[ -z $LVM2_PVSEG_START ]]; then + echo "$0: No linear segments found" + exit 1 + fi + move_start=$LVM2_PVSEG_START + move_size=$LVM2_PVSEG_SIZE + + # We're done when first free is after the last linear + [[ $free_start -gt $move_start ]] && break + + # Move last linear PEs to the free segment + from_range="$pvdev:$((move_start+move_size-free_size))-$((move_start+move_size-1))" + to_range="$pvdev:$((free_start))-$((free_start+free_size))" + echo "Moving $from_range to $to_range..." + pvmove --atomic --alloc anywhere "$from_range" "$to_range" + if [[ $? -ne 0 ]]; then + echo "$0: Fatal error doing pvmove" + exit 1 + fi +done + +# Show squeezed segment map +echo 'PV segment map after squeeze:' +pvs "$pvdev" --segments -o lvname,pvseg_start,pvseg_size,seg_le_ranges + +exit 0