--- QemuServer.orig.pm 2019-02-01 13:04:19.000000000 +0100 +++ QemuServer.patched.pm 2019-02-12 16:47:56.000000000 +0100 @@ -6461,6 +6461,46 @@ my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname); my $dst_path = PVE::Storage::path($storecfg, $dst_volid); + #BEGIN addition + my $src_storage_plugin = PVE::Storage::Plugin->lookup($src_scfg->{type}); + my $dst_storage_plugin = PVE::Storage::Plugin->lookup($dst_scfg->{type}); + + # in many cases the storage may have a better idea how to convert: + # if src and dst format is the same + # and src_storeid is dst_storeid + # and the storage has the feature + # and the feature is implemented as volume_copy / volume_snapshot_copy + # let the storage do the work as it quite sure is faster + if ( $src_format eq $dst_format ) { + if( $src_storeid eq $dst_storeid ) { + # this is the same storage + # and storage is capable of materializing snaps + if( $snapname ) { + my $canCopySnap = PVE::Storage::volume_has_feature($storecfg, 'copy', $src_volid, $snapname, undef) && $src_storage_plugin->can('volume_snapshot_copy'); + if( $canCopySnap ) { + print "delegate to storage plugin volume_snapshot_copy (snap $snapname)\n"; + $src_storage_plugin->volume_snapshot_copy($src_scfg, $src_volname, $snapname, $dst_volname); + + $src_storage_plugin->deactivate_volume($src_storeid, $src_scfg, $src_volname, $snapname); + + return 1; + } + } + + my $canCopyVolume = PVE::Storage::volume_has_feature($storecfg, 'copy', $src_volid, undef, undef) && $src_storage_plugin->can('volume_copy'); + if ( $canCopyVolume ) { + print "delegate to storage plugin: volume_copy (base)\n"; + $src_storage_plugin->volume_copy($src_scfg, $src_volname, $dst_volname); + + $src_storage_plugin->deactivate_volume($src_storeid, $src_scfg, $src_volname, $snapname); + + return 1; + } + } + # @todo: two zfs-storages might be able to receive stream from each other + } + #END addition + my $cmd = []; push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n'; push @$cmd, '-l', "snapshot.name=$snapname" if($snapname && $src_format eq "qcow2"); @@ -6487,6 +6527,11 @@ eval { run_command($cmd, timeout => undef, outfunc => $parser); }; my $err = $@; + + # added: deactivate the src-volume, even on failure + # this can be safely called as qemu_img_convert is never called on a running volume (that is not a snap) + $src_storage_plugin->deactivate_volume($src_storeid, $src_scfg, $src_volname, $snapname); + die "copy failed: $err" if $err; } }