From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id ECEA21FF0C0 for ; Wed, 21 Oct 2026 13:24:41 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 1B381215E6; Wed, 21 Oct 2026 13:24:39 +0200 (CEST) Message-ID: Date: Wed, 21 Oct 2026 13:24:27 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH storage] fix #8076: zfs: activate volume: check for existence to fix regression with cloud-init disk From: Fiona Ebner To: pve-devel@lists.proxmox.com References: <20261007114904.132273-1-f.ebner@proxmox.com> Content-Language: en-US In-Reply-To: <20261007114904.132273-1-f.ebner@proxmox.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1792581873769 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.348 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: 2236ERMSACBFYZCBMGT7KL3HZ6DT5M77 X-Message-ID-Hash: 2236ERMSACBFYZCBMGT7KL3HZ6DT5M77 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: Ping Am 07.10.26 um 1:49 PM schrieb Fiona Ebner: > 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);