[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