diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 71d6ad7..e314bfc 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -269,13 +269,13 @@ sub volume_resize { } sub volume_rollback_is_possible { - my ($cfg, $volid, $snap) = @_; + my ($cfg, $volid, $snap, $blockers) = @_; my ($storeid, $volname) = parse_volume_id($volid, 1); if ($storeid) { my $scfg = storage_config($cfg, $storeid); my $plugin = PVE::Storage::Plugin->lookup($scfg->{type}); - return $plugin->volume_rollback_is_possible($scfg, $storeid, $volname, $snap); + return $plugin->volume_rollback_is_possible($scfg, $storeid, $volname, $snap, $blockers); } elsif ($volid =~ m|^(/.+)$| && -e $volid) { die "snapshot rollback file/device '$volid' is not possible\n"; } else { diff --git a/PVE/Storage/BTRFSPlugin.pm b/PVE/Storage/BTRFSPlugin.pm index 63d307d..04b42f1 100644 --- a/PVE/Storage/BTRFSPlugin.pm +++ b/PVE/Storage/BTRFSPlugin.pm @@ -516,7 +516,7 @@ sub volume_snapshot { } sub volume_rollback_is_possible { - my ($class, $scfg, $storeid, $volname, $snap) = @_; + my ($class, $scfg, $storeid, $volname, $snap, $blockers) = @_; return 1; } diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index aeb4fff..e1f9335 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -948,8 +948,11 @@ sub volume_snapshot { return undef; } +# Asserts that a rollback to $snap on $volname is possible. +# If certain snapshots are preventing the rollback and $blockers is an array +# reference, the snapshot names can be pushed onto $blockers prior to dying. sub volume_rollback_is_possible { - my ($class, $scfg, $storeid, $volname, $snap) = @_; + my ($class, $scfg, $storeid, $volname, $snap, $blockers) = @_; return 1; } diff --git a/PVE/Storage/ZFSPoolPlugin.pm b/PVE/Storage/ZFSPoolPlugin.pm index aea2c9e..b73d895 100644 --- a/PVE/Storage/ZFSPoolPlugin.pm +++ b/PVE/Storage/ZFSPoolPlugin.pm @@ -483,18 +483,29 @@ sub volume_snapshot_rollback { } sub volume_rollback_is_possible { - my ($class, $scfg, $storeid, $volname, $snap) = @_; + my ($class, $scfg, $storeid, $volname, $snap, $blockers) = @_; # can't use '-S creation', because zfs list won't reverse the order when the # creation time is the same second, breaking at least our tests. my $snapshots = $class->zfs_get_sorted_snapshot_list($scfg, $volname, ['-s', 'creation']); - my $recentsnap = $snapshots->[-1]; - die "can't rollback, no snapshots exist at all\n" - if !defined($recentsnap); + my $found; + $blockers //= []; # not guaranteed to be set by caller + for my $snapshot ($snapshots->@*) { + if ($snapshot eq $snap) { + $found = 1; + } elsif ($found) { + push $blockers->@*, $snapshot; + } + } - die "can't rollback, '$snap' is not most recent snapshot\n" - if $snap ne $recentsnap; + my $volid = "${storeid}:${volname}"; + + die "can't rollback, snapshot '$snap' does not exist on '$volid'\n" + if !$found; + + die "can't rollback, '$snap' is not most recent snapshot on '$volid'\n" + if scalar($blockers->@*) > 0; return 1; }