From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id A3EC91FF136 for ; Mon, 09 Mar 2026 18:07:46 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 39A9F725B; Mon, 9 Mar 2026 18:07:38 +0100 (CET) From: Fiona Ebner To: pve-devel@lists.proxmox.com Subject: [PATCH qemu-server v2 17/18] snapshot: support live snapshot (remove) of qcow2 TPM drive on storage with snapshot-as-volume-chain Date: Mon, 9 Mar 2026 17:58:43 +0100 Message-ID: <20260309165913.219308-18-f.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260309165913.219308-1-f.ebner@proxmox.com> References: <20260309165913.219308-1-f.ebner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1773075525502 X-SPAM-LEVEL: Spam detection results: 0 AWL -1.069 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.408 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.819 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.903 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. 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: 5F7UBTNOYHXBYEJD3OKRDVYHKXOVFQSE X-Message-ID-Hash: 5F7UBTNOYHXBYEJD3OKRDVYHKXOVFQSE X-MailFrom: f.ebner@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 X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Adds a new drive_qmp_peer() helper to determine whether the drive is managed by the QEMU instance or QSD instance for the VM. Signed-off-by: Fiona Ebner --- src/PVE/QemuServer.pm | 30 +++++++++++++----------------- src/PVE/QemuServer/Drive.pm | 8 ++++++++ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm index 04fde77b..1f7afaeb 100644 --- a/src/PVE/QemuServer.pm +++ b/src/PVE/QemuServer.pm @@ -83,7 +83,7 @@ use PVE::QemuServer::DriveDevice qw(print_drivedevice_full scsihw_infos); use PVE::QemuServer::Machine; use PVE::QemuServer::Memory qw(get_current_memory); use PVE::QemuServer::MetaInfo; -use PVE::QemuServer::Monitor qw(mon_cmd vm_qmp_peer); +use PVE::QemuServer::Monitor qw(mon_cmd qmp_cmd vm_qmp_peer); use PVE::QemuServer::Network; use PVE::QemuServer::OVMF; use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port parse_hostpci); @@ -4342,7 +4342,8 @@ sub qemu_volume_snapshot { if ($do_snapshots_type eq 'internal') { print "internal qemu snapshot\n"; - mon_cmd($vmid, 'blockdev-snapshot-internal-sync', device => $deviceid, name => $snap); + my $qmp_peer = PVE::QemuServer::Drive::drive_qmp_peer($storecfg, $vmid, $drive); + qmp_cmd($qmp_peer, 'blockdev-snapshot-internal-sync', device => $deviceid, name => $snap); } elsif ($do_snapshots_type eq 'external') { my $machine_version = PVE::QemuServer::Machine::get_current_qemu_machine($vmid); if (!PVE::QemuServer::Machine::is_machine_version_at_least($machine_version, 10, 0)) { @@ -4355,14 +4356,9 @@ sub qemu_volume_snapshot { print "external qemu snapshot\n"; my $snapshots = PVE::Storage::volume_snapshot_info($storecfg, $volid); my $parent_snap = $snapshots->{'current'}->{parent}; + my $qmp_peer = PVE::QemuServer::Drive::drive_qmp_peer($storecfg, $vmid, $drive); PVE::QemuServer::VolumeChain::blockdev_external_snapshot( - $storecfg, - vm_qmp_peer($vmid), - $machine_version, - $deviceid, - $drive, - $snap, - $parent_snap, + $storecfg, $qmp_peer, $machine_version, $deviceid, $drive, $snap, $parent_snap, ); } elsif ($do_snapshots_type eq 'storage') { PVE::Storage::volume_snapshot($storecfg, $volid, $snap); @@ -4390,8 +4386,9 @@ sub qemu_volume_snapshot_delete { my $do_snapshots_type = do_snapshots_type($storecfg, $volid, $attached_deviceid, $running); if ($do_snapshots_type eq 'internal') { - mon_cmd( - $vmid, + my $qmp_peer = PVE::QemuServer::Drive::drive_qmp_peer($storecfg, $vmid, $drive); + qmp_cmd( + $qmp_peer, 'blockdev-snapshot-delete-internal-sync', device => $attached_deviceid, name => $snap, @@ -4415,13 +4412,15 @@ sub qemu_volume_snapshot_delete { my $parentsnap = $snapshots->{$snap}->{parent}; my $childsnap = $snapshots->{$snap}->{child}; + my $qmp_peer = PVE::QemuServer::Drive::drive_qmp_peer($storecfg, $vmid, $drive); + # if we delete the first snasphot, we commit because the first snapshot original base image, it should be big. # improve-me: if firstsnap > child : commit, if firstsnap < child do a stream. if (!$parentsnap) { print "delete first snapshot $snap\n"; PVE::QemuServer::VolumeChain::blockdev_commit( $storecfg, - vm_qmp_peer($vmid), + $qmp_peer, $machine_version, $attached_deviceid, $drive, @@ -4433,7 +4432,7 @@ sub qemu_volume_snapshot_delete { PVE::QemuServer::VolumeChain::blockdev_replace( $storecfg, - vm_qmp_peer($vmid), + $qmp_peer, $machine_version, $attached_deviceid, $drive, @@ -4446,7 +4445,7 @@ sub qemu_volume_snapshot_delete { print "stream intermediate snapshot $snap to $childsnap\n"; PVE::QemuServer::VolumeChain::blockdev_stream( $storecfg, - vm_qmp_peer($vmid), + $qmp_peer, $machine_version, $attached_deviceid, $drive, @@ -7775,9 +7774,6 @@ sub restore_tar_archive { sub do_snapshots_type { my ($storecfg, $volid, $deviceid, $running) = @_; - #always use storage snapshot for tpmstate - return 'storage' if $deviceid && $deviceid =~ m/tpmstate0/; - #we use storage snapshot if vm is not running or if disk is unused; return 'storage' if !$running || !$deviceid; diff --git a/src/PVE/QemuServer/Drive.pm b/src/PVE/QemuServer/Drive.pm index f88504b2..79afc146 100644 --- a/src/PVE/QemuServer/Drive.pm +++ b/src/PVE/QemuServer/Drive.pm @@ -13,6 +13,8 @@ use PVE::Storage; use PVE::Storage::Common; use PVE::JSONSchema qw(get_standard_option); +use PVE::QemuServer::Monitor qw(qsd_peer vm_qmp_peer); + use base qw(Exporter); our @EXPORT_OK = qw( @@ -1164,4 +1166,10 @@ sub drive_uses_qsd_fuse { return; } +sub drive_qmp_peer { + my ($storecfg, $vmid, $drive) = @_; + + return drive_uses_qsd_fuse($storecfg, $drive) ? qsd_peer($vmid) : vm_qmp_peer($vmid); +} + 1; -- 2.47.3