From a9315a0ed32293d11a56470d2e19598a5212e8e3 Mon Sep 17 00:00:00 2001 From: Shannon Sterz Date: Tue, 29 Jul 2025 14:11:51 +0200 Subject: [PATCH] fix #6561: zfspool: track refquota for subvolumes via user properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ZFS itself does not track the refquota per snapshot, so this needs to be handled by Proxmox VE. Otherwise, rolling back a volume that has been resized since the snapshot was taken, will retain the new size. This is problematic, as it means the value in the guest config does not match the size of the disk on the storage anymore. This implementation does so by leveraging a user property per snapshot. Reported-by: Lukas Wagner Suggested-by: Fabian Grünbichler Signed-off-by: Shannon Sterz Reviewed-by: Fiona Ebner Link: https://lore.proxmox.com/20250729121151.159797-1-s.sterz@proxmox.com [FE: improve capitalization and wording in commit message] Signed-off-by: Fiona Ebner --- src/PVE/Storage/ZFSPoolPlugin.pm | 38 +++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/PVE/Storage/ZFSPoolPlugin.pm b/src/PVE/Storage/ZFSPoolPlugin.pm index cdf5868..d8d8d0f 100644 --- a/src/PVE/Storage/ZFSPoolPlugin.pm +++ b/src/PVE/Storage/ZFSPoolPlugin.pm @@ -482,9 +482,25 @@ sub volume_size_info { sub volume_snapshot { my ($class, $scfg, $storeid, $volname, $snap) = @_; - my $vname = ($class->parse_volname($volname))[1]; + my (undef, $vname, undef, undef, undef, undef, $format) = $class->parse_volname($volname); + my $snapshot_name = "$scfg->{pool}/$vname\@$snap"; - $class->zfs_request($scfg, undef, 'snapshot', "$scfg->{pool}/$vname\@$snap"); + $class->zfs_request($scfg, undef, 'snapshot', $snapshot_name); + + # if this is a subvol, track refquota information via user properties. zfs + # does not track this property for snapshosts and consequently does not roll + # it back. so track this information manually. + if ($format eq 'subvol') { + my $refquota = $class->zfs_get_properties($scfg, 'refquota', "$scfg->{pool}/$vname"); + + $class->zfs_request( + $scfg, + undef, + 'set', + "pve-storage:refquota=${refquota}", + $snapshot_name, + ); + } } sub volume_snapshot_delete { @@ -500,8 +516,24 @@ sub volume_snapshot_rollback { my ($class, $scfg, $storeid, $volname, $snap) = @_; my (undef, $vname, undef, undef, undef, undef, $format) = $class->parse_volname($volname); + my $snapshot_name = "$scfg->{pool}/$vname\@$snap"; - my $msg = $class->zfs_request($scfg, undef, 'rollback', "$scfg->{pool}/$vname\@$snap"); + my $msg = $class->zfs_request($scfg, undef, 'rollback', $snapshot_name); + + # if this is a subvol, check if we tracked the refquota manually via user + # properties and if so, set it appropriatelly again. + if ($format eq 'subvol') { + my $refquota = $class->zfs_get_properties($scfg, 'pve-storage:refquota', $snapshot_name); + + if ($refquota =~ m/^\d+$/) { + $class->zfs_request( + $scfg, undef, 'set', "refquota=${refquota}", "$scfg->{pool}/$vname", + ); + } elsif ($refquota ne "-") { + # refquota user property was set, but not a number -> warn + warn "property for refquota tracking contained unknown value '$refquota'\n"; + } + } # we have to unmount rollbacked subvols, to invalidate wrong kernel # caches, they get mounted in activate volume again