From 5e2e5a8cbe6c125cad59f65d59833df2ec463213 Mon Sep 17 00:00:00 2001 From: Kevin Adams Date: Sun, 24 May 2026 16:28:32 -0400 Subject: [PATCH] fix: allow free_image on detached disks while VM is running (#258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed _vm_is_running() check from free_image. When a disk is detached from a running VM (unused0), QEMU immediately closes its libiscsi connection — there is no active session to block the delete. The force=true flag on the TrueNAS extent DELETE is the correct guard for any residual session. The VM-running check was overly broad and blocked legitimate deletes of already-detached disks. Co-Authored-By: Claude Sonnet 4.6 --- perl5/PVE/Storage/Custom/TrueNAS.pm | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/perl5/PVE/Storage/Custom/TrueNAS.pm b/perl5/PVE/Storage/Custom/TrueNAS.pm index 87792dc..feb875e 100644 --- a/perl5/PVE/Storage/Custom/TrueNAS.pm +++ b/perl5/PVE/Storage/Custom/TrueNAS.pm @@ -309,17 +309,6 @@ sub _maybe_cleanup_vm_target { } # Returns true if the QEMU process for $vmid is alive. -sub _vm_is_running { - my ($vmid) = @_; - my $pidfile = "/var/run/qemu-server/$vmid.pid"; - return 0 unless -f $pidfile; - open(my $pf, '<', $pidfile) or return 0; - my $pidraw = <$pf>; - close($pf); - my ($pid) = ($pidraw // '') =~ /^(\d+)/; # untaint for -T - return ($pid && kill(0, $pid)) ? 1 : 0; -} - # Returns the next unused LUN ID on the given target sub _next_lun_id { my ($scfg, $target_id) = @_; @@ -436,20 +425,14 @@ sub free_image { _log('info', "free_image: removing $volname"); - # Refuse if the disk's owning VM is still running — QEMU still holds an - # iSCSI connection to the per-VM target, so extent DELETE would be blocked. my ($vmid) = $volname =~ /^(?:vm|base)-(\d+)-/; - if ($vmid && _vm_is_running($vmid)) { - die "free_image: cannot delete '$volname' — VM $vmid is still running. " - . "Stop the VM first.\n"; - } my $ext = _find_extent($scfg, $volname); if ($ext) { - # With per-VM targets and iscsi:// paths, QEMU's libiscsi connection - # closes when the VM stops. TrueNAS sees no active session on the - # VM's target, so force=true succeeds without stopping the service. + # force=true tells TrueNAS to disconnect any remaining iSCSI session + # before deleting. For detached disks on a running VM, QEMU has + # already closed the libiscsi connection, so this is a no-op safety net. eval { _api($scfg, 'DELETE', "/iscsi/extent/id/$ext->{extent_id}", { force => JSON::true });