X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FStorage%2FZFSPoolPlugin.pm;h=660b3d9b18783eab37c1d7f9ac0f51e59c7f68d6;hb=ab3516a6d7bce0cf7d269576ac496ecb73b1f005;hp=2f0a80a4613a6eef0256730c261661745a5ef6ff;hpb=3893d2755e523cd81cf6a72253d5345bd555a8db;p=pve-storage.git diff --git a/PVE/Storage/ZFSPoolPlugin.pm b/PVE/Storage/ZFSPoolPlugin.pm index 2f0a80a..660b3d9 100644 --- a/PVE/Storage/ZFSPoolPlugin.pm +++ b/PVE/Storage/ZFSPoolPlugin.pm @@ -7,6 +7,7 @@ use IO::File; use Net::IP; use POSIX; +use PVE::ProcFSTools; use PVE::RPCEnvironment; use PVE::Storage::Plugin; use PVE::Tools qw(run_command); @@ -133,6 +134,8 @@ sub on_add_hook { } else { $scfg->{mountpoint} = $mountpoint; } + + return; } sub path { @@ -331,9 +334,10 @@ sub zfs_create_subvol { my ($class, $scfg, $volname, $size) = @_; my $dataset = "$scfg->{pool}/$volname"; + my $quota = $size ? "${size}k" : "none"; my $cmd = ['create', '-o', 'acltype=posixacl', '-o', 'xattr=sa', - '-o', "refquota=${size}k", $dataset]; + '-o', "refquota=${quota}", $dataset]; $class->zfs_request($scfg, undef, @$cmd); } @@ -465,9 +469,21 @@ sub volume_snapshot_delete { sub volume_snapshot_rollback { 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 $msg = $class->zfs_request($scfg, undef, 'rollback', "$scfg->{pool}/$vname\@$snap"); + + # we have to unmount rollbacked subvols, to invalidate wrong kernel + # caches, they get mounted in activate volume again + # see zfs bug #10931 https://github.com/openzfs/zfs/issues/10931 + if ($format eq 'subvol') { + eval { $class->zfs_request($scfg, undef, 'unmount', "$scfg->{pool}/$vname"); }; + if (my $err = $@) { + die $err if $err !~ m/not currently mounted$/; + } + } - $class->zfs_request($scfg, undef, 'rollback', "$scfg->{pool}/$vname\@$snap"); + return $msg; } sub volume_rollback_is_possible { @@ -510,32 +526,49 @@ sub volume_snapshot_list { return $snaps; } +my sub dataset_mounted_heuristic { + my ($dataset) = @_; + + my $mounts = PVE::ProcFSTools::parse_proc_mounts(); + for my $mp (@$mounts) { + my ($what, $dir, $fs) = $mp->@*; + next if $fs ne 'zfs'; + # check for root-dataset or any child-dataset (root-dataset could have 'canmount=off') + # If any child is mounted heuristically assume that `zfs mount -a` was successful + next if $what !~ m!^$dataset(?:/|$)!; + return 1; + } + return 0; +} + sub activate_storage { my ($class, $storeid, $scfg, $cache) = @_; # Note: $scfg->{pool} can include dataset / - my $pool = $scfg->{pool}; - $pool =~ s!/.*$!!; + my $dataset = $scfg->{pool}; + my $pool = ($dataset =~ s!/.*$!!r); + + return 1 if dataset_mounted_heuristic($dataset); # early return my $pool_imported = sub { - my @param = ('-o', 'name', '-H', "$pool"); + my @param = ('-o', 'name', '-H', $pool); my $res = eval { $class->zfs_request($scfg, undef, 'zpool_list', @param) }; - if ($@) { - warn "$@\n"; - return undef; - } + warn "$@\n" if $@; + return defined($res) && $res =~ m/$pool/; }; if (!$pool_imported->()) { # import can only be done if not yet imported! - my @param = ('-d', '/dev/disk/by-id/', '-o', 'cachefile=none', "$pool"); + my @param = ('-d', '/dev/disk/by-id/', '-o', 'cachefile=none', $pool); eval { $class->zfs_request($scfg, undef, 'zpool_import', @param) }; if (my $err = $@) { # just could've raced with another import, so recheck if it is imported - die "could not activate storage '$storeid', $@\n" if !$pool_imported->(); + die "could not activate storage '$storeid', $err\n" if !$pool_imported->(); } } + eval { $class->zfs_request($scfg, undef, 'mount', '-a') }; + die "could not activate storage '$storeid', $@\n" if $@; return 1; } @@ -717,7 +750,7 @@ sub volume_export_formats { } sub volume_import { - my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots, $allow_rename) = @_; + my ($class, $scfg, $storeid, $fh, $volname, $format, $snapshot, $base_snapshot, $with_snapshots, $allow_rename) = @_; die "unsupported import stream format for $class: $format\n" if $format ne 'zfs'; @@ -754,9 +787,9 @@ sub volume_import { } sub volume_import_formats { - my ($class, $scfg, $storeid, $volname, $base_snapshot, $with_snapshots) = @_; + my ($class, $scfg, $storeid, $volname, $snapshot, $base_snapshot, $with_snapshots) = @_; - return $class->volume_export_formats($scfg, $storeid, $volname, undef, $base_snapshot, $with_snapshots); + return $class->volume_export_formats($scfg, $storeid, $volname, $snapshot, $base_snapshot, $with_snapshots); } 1;