From f1841228ea6f92edccd04dfae834d9fa85404512 Mon Sep 17 00:00:00 2001 From: Ilia Ross Date: Fri, 17 Jul 2026 20:34:36 +0200 Subject: [PATCH] Fix LVM resizing for expanded partition-backed disks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⓘ Grow eligible PV partitions into adjacent free space before retrying `pvresize`, and treat unchanged "use all free VG space" LV targets as no-ops. --- CHANGELOG.md | 1 + lvm/lang/en | 1 + lvm/lvm-lib.pl | 51 +++++++++++++++++++++++++++++++++++++++++++++++-- lvm/save_lv.cgi | 5 ++++- lvm/save_pv.cgi | 7 +++++++ 5 files changed, 62 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cb600c66..3aaa6fdfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Fix missing Maildir folders to be counted as empty in Mailboxes module * Fix Postfix version comparisons to handle version strings safely * Fix SELinux labeling for Webmin runtime data +* Fix LVM resizing to grow eligible partition-backed physical volumes into adjacent free disk space and handle unchanged logical volume sizes correctly * Update the Authentic theme to the latest version with various improvements: - Fix inconsistent gaps around rounded UI elements - Fix CPU usage values exceeding 100% in the dashboard diff --git a/lvm/lang/en b/lvm/lang/en index f2ee24ad3..67bb0a72f 100644 --- a/lvm/lang/en +++ b/lvm/lang/en @@ -170,6 +170,7 @@ pv_resize=Resize To Match Device pv_err=Failed to save physical volume pv_err2=Failed to remove physical volume pv_err3=Failed to resize physical volume +pv_enoresize=Physical volume $1 is already the size of its underlying device. If the device is a partition, expand the partition first and then resize the physical volume. pv_delete=Remove Physical Volume pv_rusure=Are you sure you want to remove physical volume device $1 from its volume group? This will result in any data being shifted to other physical volumes within the group. pv_deleteok=Remove Volume diff --git a/lvm/lvm-lib.pl b/lvm/lvm-lib.pl index 3bc87dc2d..deb771471 100755 --- a/lvm/lvm-lib.pl +++ b/lvm/lvm-lib.pl @@ -151,9 +151,56 @@ return $? ? $out : undef; # Set the size of a physical volume to match the underlying device sub resize_physical_volume { -local $cmd = "pvresize ".quotemeta($_[0]->{'device'}); +local ($pv) = @_; +local $cmd = "pvresize ".quotemeta($pv->{'device'}); local $out = &backquote_logged("$cmd 2>&1"); -return $? ? $out : undef; +return $out if ($?); + +# If the PV did not change, its partition may have adjacent free space +return undef if (!defined($pv->{'pe_total'})); +local ($newpv) = grep { $_->{'device'} eq $pv->{'device'} } + &list_physical_volumes($pv->{'vg'}); +return undef if (!$newpv || !defined($newpv->{'pe_total'}) || + $newpv->{'pe_total'} != $pv->{'pe_total'}); +local ($grew, $err) = &grow_physical_volume_partition($pv); +return $err if ($err); +if ($grew) { + $out = &backquote_logged("$cmd 2>&1"); + return $out if ($?); + } +return undef; +} + +# grow_physical_volume_partition(&pv) +# Grow a partition-backed PV into adjacent free disk space, if possible +sub grow_physical_volume_partition +{ +local ($pv) = @_; +return (0, undef) if (!&has_command("growpart")); +local $pvdev = &simplify_path(&resolve_links($pv->{'device'})); +local ($disk, $part); +DISK: foreach $d (&fdisk::list_disks_partitions()) { + foreach $p (@{$d->{'parts'}}) { + local $pdev = &simplify_path(&resolve_links($p->{'device'})); + if ($pvdev eq $pdev && + $p->{'number'} =~ /^\d+$/) { + $disk = $d; + $part = $p; + last DISK; + } + } + } +return (0, undef) if (!$disk); + +# Only modify the partition when growpart confirms that it can be enlarged +local $cmd = "growpart -N ".quotemeta($disk->{'device'})." ". + quotemeta($part->{'number'}); +&backquote_command("$cmd 2>&1"); +return (0, undef) if ($?); +$cmd = "growpart ".quotemeta($disk->{'device'})." ". + quotemeta($part->{'number'}); +local $out = &backquote_logged("$cmd 2>&1"); +return $? ? (0, $out) : (1, undef); } # list_volume_groups() diff --git a/lvm/save_lv.cgi b/lvm/save_lv.cgi index fcbc5e9b7..51e425d70 100755 --- a/lvm/save_lv.cgi +++ b/lvm/save_lv.cgi @@ -180,7 +180,10 @@ else { $realsize = ($vg->{'pe_total'}*$vg->{'pe_size'})-($vg->{'pe_alloc'}*$vg->{'pe_size'})+$lv->{'size'}; } - if ($in{'sizeconfirm'}) { + if ($realsize == $lv->{'size'}) { + # No resize is needed + } + elsif ($in{'sizeconfirm'}) { # Just resize the logical volume $err = &resize_logical_volume($lv, $realsize); &error("
$err
") if ($err); diff --git a/lvm/save_pv.cgi b/lvm/save_pv.cgi index 2053fa1f2..55020c73a 100755 --- a/lvm/save_pv.cgi +++ b/lvm/save_pv.cgi @@ -39,6 +39,13 @@ elsif ($in{'resize'}) { &error_setup($text{'pv_err3'}); $err = &resize_physical_volume($pv); &error("
$err
") if ($err); + ($newpv) = grep { $_->{'device'} eq $pv->{'device'} } + &list_physical_volumes($in{'vg'}); + if ($newpv && defined($pv->{'pe_total'}) && + defined($newpv->{'pe_total'}) && + $newpv->{'pe_total'} == $pv->{'pe_total'}) { + &error(&text('pv_enoresize', "$pv->{'device'}")); + } &webmin_log("resize", "pv", $in{'pv'}, $pv); &redirect("index.cgi?mode=pvs"); }