From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id A0A6A1FF0C0 for ; Wed, 04 Nov 2026 10:30:17 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 0AE5B214E4; Wed, 04 Nov 2026 10:29:58 +0100 (CET) From: Thomas Ellmenreich To: pve-devel@lists.proxmox.com Subject: [PATCH pve-container 2/2] mountpoint: allow changing rootfs properties at runtime Date: Wed, 4 Nov 2026 10:29:39 +0100 Message-ID: <20261104092939.123574-3-t.ellmenreich@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261104092939.123574-1-t.ellmenreich@proxmox.com> References: <20261104092939.123574-1-t.ellmenreich@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1793784593344 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.358 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: E45DF5V733RRWWERGRU2KFXMQLBGDVPU X-Message-ID-Hash: E45DF5V733RRWWERGRU2KFXMQLBGDVPU X-MailFrom: t.ellmenreich@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Thomas Ellmenreich X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Just as has been implemented for mountpoints, properties like replicate can now be applied at runtime for rootfs disks. If the change is performed with any other non hot pluggable options, the whole changeset is added as pending instead of mixing the two states. Signed-off-by: Thomas Ellmenreich --- src/PVE/LXC/Config.pm | 2 +- src/test/config_tests.pl | 65 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm index 60318b4..5c35750 100644 --- a/src/PVE/LXC/Config.pm +++ b/src/PVE/LXC/Config.pm @@ -1737,7 +1737,7 @@ sub vmconfig_hotplug_pending { if (!$hotplug_memory_done) { # don't call twice if both opts are passed $hotplug_memory->($conf->{pending}->{memory}, $conf->{pending}->{swap}); } - } elsif ($opt =~ m/^mp(\d+)$/) { + } elsif ($opt =~ m/^mp(\d+)$/ || $opt eq 'rootfs') { $class->apply_pending_mountpoint($vmid, $conf, $opt, $storecfg, 1); # apply_pending_mountpoint modifies the value if it creates a new disk $value = $conf->{pending}->{$opt}; diff --git a/src/test/config_tests.pl b/src/test/config_tests.pl index 43935a9..5c5e868 100755 --- a/src/test/config_tests.pl +++ b/src/test/config_tests.pl @@ -9,14 +9,19 @@ use Test::More; use PVE::LXC::Config; +# Creates new and old configurations based on the common core and just +# the changes. The fourth parameter can change the kind of mountpoint it +# is, instead of always using mp0. my sub create_conf { - my ($common, $new, $old) = @_; + my ($common, $new, $old, $mountpoint_name) = @_; + + $mountpoint_name //= 'mp0'; my $new_str = defined($new) ? $common . ',' . $new : $common; my $old_str = defined($old) ? $common . ',' . $old : $common; return ( - PVE::LXC::Config->parse_volume('mp0', $new_str), - PVE::LXC::Config->parse_volume('mp0', $old_str), + PVE::LXC::Config->parse_volume($mountpoint_name, $new_str), + PVE::LXC::Config->parse_volume($mountpoint_name, $old_str), ); } @@ -27,6 +32,14 @@ subtest 'same config can be applied' => sub { ok($result, "can be hotplugged"); }; +subtest 'rootfs same config can be applied' => sub { + my ($new, $old) = + create_conf("local:100/vm-100-disk-1.raw,replicate=1", undef, undef, "rootfs"); + my $result = PVE::LXC::Config->__mountpoint_config_fast_plug_safe("rootfs", $new, $old); + + ok($result, "can be hotplugged"); +}; + subtest 'config with only backup difference can be applied' => sub { my ($new, $old) = create_conf("local:100/vm-100-disk-1.raw,mp=/mnt", "backup=1", "backup=0"); @@ -35,6 +48,14 @@ subtest 'config with only backup difference can be applied' => sub { ok($result, "can be hotplugged"); }; +subtest 'rootfs config with only backup difference can be applied' => sub { + my ($new, $old) = + create_conf("local:100/vm-100-disk-1.raw", "replicate=1", "replicate=0", "rootfs"); + my $result = PVE::LXC::Config->__mountpoint_config_fast_plug_safe("rootfs", $new, $old); + + ok($result, "can be hotplugged"); +}; + subtest 'fast plug option also ignored if previously not present' => sub { my ($new, $old) = create_conf("local:100/vm-100-disk-1.raw,mp=/mnt", "replicate=1", undef); my $result = PVE::LXC::Config->__mountpoint_config_fast_plug_safe("mp0", $new, $old); @@ -42,6 +63,14 @@ subtest 'fast plug option also ignored if previously not present' => sub { ok($result, "can be hotplugged"); }; +subtest 'rootfs fast plug option also ignored if previously not present' => sub { + my ($new, $old) = + create_conf("local:100/vm-100-disk-1.raw", "replicate=1", undef, "rootfs"); + my $result = PVE::LXC::Config->__mountpoint_config_fast_plug_safe("rootfs", $new, $old); + + ok($result, "can be hotplugged"); +}; + subtest 'difference in mountpoint cannot be applied' => sub { my ($new, $old) = create_conf("local:100/vm-100-disk-1.raw,replicate=1", "mp=/mnt/one", "mp=/mnt/two"); @@ -50,6 +79,15 @@ subtest 'difference in mountpoint cannot be applied' => sub { ok(!$result, "cannot be hotplugged"); }; +subtest 'rootfs difference in acl cannot be applied' => sub { + my ($new, $old) = create_conf( + "local:100/vm-100-disk-1.raw,replicate=1", "acl=0", "acl=1", "rootfs", + ); + my $result = PVE::LXC::Config->__mountpoint_config_fast_plug_safe("rootfs", $new, $old); + + ok(!$result, "cannot be hotplugged"); +}; + subtest 'changing fast pluggable and non fast pluggable cannot be applied' => sub { my ($new, $old) = create_conf("local:100/vm-100-disk-1.raw", "mp=/mnt/one", "mp=/mnt/two,replicate=1"); @@ -58,6 +96,15 @@ subtest 'changing fast pluggable and non fast pluggable cannot be applied' => su ok(!$result, "cannot be hotplugged"); }; +subtest 'rootfs changing fast pluggable and non fast pluggable cannot be applied' => sub { + my ($new, $old) = create_conf( + "local:100/vm-100-disk-1.raw", "acl=0", "acl=1,replicate=1", "rootfs", + ); + my $result = PVE::LXC::Config->__mountpoint_config_fast_plug_safe("rootfs", $new, $old); + + ok(!$result, "cannot be hotplugged"); +}; + subtest 'idmap array does not throw off comparison' => sub { my ($new, $old) = create_conf( "local:100/vm-100-disk-1.raw,mp=/mnt,idmap=u:0:100000:65536;g:0:100000:65536", @@ -69,4 +116,16 @@ subtest 'idmap array does not throw off comparison' => sub { ok($result, "can be hotplugged"); }; +subtest 'rootfs idmap array does not throw off comparison' => sub { + my ($new, $old) = create_conf( + "local:100/vm-100-disk-1.raw,idmap=u:0:100000:65536;g:0:100000:65536", + "replicate=1", + undef, + "rootfs", + ); + my $result = PVE::LXC::Config->__mountpoint_config_fast_plug_safe("rootfs", $new, $old); + + ok($result, "can be hotplugged"); +}; + done_testing(); -- 2.47.3