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 2AB051FF0AB for ; Wed, 07 Oct 2026 13:49:20 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 0835F213A5; Wed, 07 Oct 2026 13:49:17 +0200 (CEST) From: Fiona Ebner To: pve-devel@lists.proxmox.com Subject: [PATCH storage] fix #8076: zfs: activate volume: check for existence to fix regression with cloud-init disk Date: Wed, 7 Oct 2026 13:48:57 +0200 Message-ID: <20261007114904.132273-1-f.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1791373751363 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.456 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: 4MQS2PHSDUV6E2TBHDWEDCZVWMJPXEJK X-Message-ID-Hash: 4MQS2PHSDUV6E2TBHDWEDCZVWMJPXEJK 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: Explicitly checking for existence during activation has the advantage to catch issues earlier with a clearer error message. Note that the implementation in Plugin.pm already explicitly checks for existence, so this also aligns the implementation for ZFS closer to that. This also fixes #8076: For a zvol (i.e. 'raw' format), zfs_wait_for_zvol_link() was called without first checking if the volume actually exists. This means that for non-existent volumes, activation would only fail after the timeout of 300 seconds in worker context. This change also means that non-existent snapshots are caught during activation already, since previously, activate_volume() would return early without doing anything for snapshots. The error message "dataset does not exist" is matched against, because the exit status from 'zfs' will always be 1 if an error occured; from the man page: > The zfs utility exits 0 on success, 1 if an error occurs, and 2 if > invalid command line options were specified. Note that zfs_delete_zvol() already does the same. Signed-off-by: Fiona Ebner --- src/PVE/Storage/ZFSPoolPlugin.pm | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/PVE/Storage/ZFSPoolPlugin.pm b/src/PVE/Storage/ZFSPoolPlugin.pm index 61c49d9..023bd21 100644 --- a/src/PVE/Storage/ZFSPoolPlugin.pm +++ b/src/PVE/Storage/ZFSPoolPlugin.pm @@ -288,6 +288,21 @@ sub zfs_request { return $msg; } +my sub zfs_volume_exists { + my ($class, $scfg, $volname, $snapname) = @_; + + my $name = ($class->parse_volname($volname))[1]; + my $dataset = "$scfg->{pool}/${name}"; + $dataset .= "\@${snapname}" if defined($snapname); + + eval { $class->zfs_request($scfg, 10, 'list', '-o', 'name', '-Hp', $dataset); }; + if (my $err = $@) { + return 0 if $err =~ m/dataset does not exist/; + die $err; + } + return 1; +} + sub zfs_wait_for_zvol_link { my ($class, $scfg, $volname, $timeout) = @_; @@ -739,6 +754,12 @@ sub deactivate_storage { sub activate_volume { my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_; + if (!zfs_volume_exists($class, $scfg, $volname, $snapname)) { + my $name = "$volname"; + $name .= "\@${snapname}" if defined($snapname); + die "volume ${name} does not exist on storage ${storeid}\n"; + } + return 1 if defined($snapname); my (undef, $dataset, undef, undef, undef, undef, $format) = $class->parse_volname($volname); -- 2.47.3