[pve-devel] [PATCH 1/7] split qemu_drive_mirror_monitor from qemu_drive_mirror.
Alexandre Derumier
aderumier at odiso.com
Thu Oct 20 02:35:10 CEST 2016
we can use multiple drive_mirror in parralel
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
PVE/QemuServer.pm | 98 +++++++++++++++++++++++++++++++++----------------------
1 file changed, 59 insertions(+), 39 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 728110f..a5aa4c7 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -5817,70 +5817,90 @@ sub qemu_drive_mirror {
my $opts = { timeout => 10, device => "drive-$drive", mode => "existing", sync => "full", target => $qemu_target };
$opts->{format} = $format if $format;
- print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
+ print "drive mirror is starting for drive-$drive\n";
- my $finish_job = sub {
- while (1) {
- my $stats = vm_mon_cmd($vmid, "query-block-jobs");
- my $stat = @$stats[0];
- last if !$stat;
- sleep 1;
+ vm_mon_cmd($vmid, "drive-mirror", %$opts);
+
+}
+
+sub qemu_drive_mirror_monitor {
+ my ($vmid, $vmiddst, $skipcomplete) = @_;
+
+ my $err_complete = 0;
+ my $last_nb_running_jobs = 0;
+ my @drives = ();
+
+ my $cancel_job = sub {
+ my $drives = @_;
+ foreach my $drive (@drives) {
+ vm_mon_cmd($vmid, "block-job-cancel", device => $drive);
}
};
eval {
- vm_mon_cmd($vmid, "drive-mirror", %$opts);
while (1) {
my $stats = vm_mon_cmd($vmid, "query-block-jobs");
- my $stat = @$stats[0];
- die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
- die "error job is not mirroring" if $stat->{type} ne "mirror";
- my $busy = $stat->{busy};
- my $ready = $stat->{ready};
+ die "too much complete error, migration can't finish" if $err_complete > 300;
+ die "Some mirroring jobs seem to be aborded. Maybe do you have bad sectors?" if @$stats < $last_nb_running_jobs;
- if (my $total = $stat->{len}) {
- my $transferred = $stat->{offset} || 0;
- my $remaining = $total - $transferred;
- my $percent = sprintf "%.2f", ($transferred * 100 / $total);
+ last if @$stats == 0 && $last_nb_running_jobs == 0; #no more block-job running
+ my $readycounter = 0;
+ @drives = ();
+ $last_nb_running_jobs = @$stats;
- print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
- }
+ foreach my $stat (@$stats) {
+ die "error job is not mirroring" if $stat->{type} ne "mirror";
+ my $busy = $stat->{busy};
+ my $ready = $stat->{ready};
+ push @drives, $stat->{device};
+ if (my $total = $stat->{len}) {
+ my $transferred = $stat->{offset} || 0;
+ my $remaining = $total - $transferred;
+ my $percent = sprintf "%.2f", ($transferred * 100 / $total);
- if ($stat->{ready} eq 'true') {
+ print "$stat->{device} transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
+ }
+
+ $readycounter++ if $stat->{ready} eq 'true';
+ }
- last if $vmiddst != $vmid;
+ if ($readycounter == @$stats) {
+ print "all drives are ready \n";
+ last if $skipcomplete; #do the complete later
- # try to switch the disk if source and destination are on the same guest
- eval { vm_mon_cmd($vmid, "block-job-complete", device => "drive-$drive") };
- if (!$@) {
- &$finish_job();
- last;
+ if ($vmiddst && $vmiddst != $vmid) {
+ # if we clone a disk for a new target vm, we don't switch the disk
+ eval { &$cancel_job(@drives); };
+ $last_nb_running_jobs = 0;
+ } else {
+ foreach my $drive (@drives) {
+ # try to switch the disk if source and destination are on the same guest
+ print "Try to complete block job for drive $drive \n";
+
+ eval { vm_mon_cmd($vmid, "block-job-complete", device => $drive) };
+ if ($@ =~ m/cannot be completed/) {
+ print "block job cannot be complete for drive $drive. Try again \n";
+ $err_complete++;
+ }else {
+ print "complete ok for drive $drive \n";
+ $last_nb_running_jobs--;
+ }
+ }
}
- die $@ if $@ !~ m/cannot be completed/;
}
+ last if $last_nb_running_jobs == 0;
sleep 1;
}
-
-
};
my $err = $@;
- my $cancel_job = sub {
- vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive");
- &$finish_job();
- };
-
if ($err) {
- eval { &$cancel_job(); };
+ eval { &$cancel_job(@drives); };
die "mirroring error: $err";
}
- if ($vmiddst != $vmid) {
- # if we clone a disk for a new target vm, we don't switch the disk
- &$cancel_job(); # so we call block-job-cancel
- }
}
sub clone_disk {
--
2.1.4
More information about the pve-devel
mailing list