summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--block-migration.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/block-migration.c b/block-migration.c
index 5274c5ec37..15b76de9bc 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -43,6 +43,7 @@ typedef struct BlkMigDevState {
     int bulk_completed;
     int shared_base;
     int64_t cur_sector;
+    int64_t completed_sectors;
     int64_t total_sectors;
     int64_t dirty;
     QSIMPLEQ_ENTRY(BlkMigDevState) entry;
@@ -67,6 +68,7 @@ typedef struct BlkMigState {
     int submitted;
     int read_done;
     int transferred;
+    int64_t total_sector_sum;
     int64_t print_completion;
 } BlkMigState;
 
@@ -118,16 +120,11 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds, int is_async)
     }
 
     if (cur_sector >= total_sectors) {
-        bmds->cur_sector = total_sectors;
+        bmds->cur_sector = bmds->completed_sectors = total_sectors;
         return 1;
     }
 
-    if (cur_sector >= block_mig_state.print_completion) {
-        printf("Completed %" PRId64 " %%\r", cur_sector * 100 / total_sectors);
-        fflush(stdout);
-        block_mig_state.print_completion +=
-            (BDRV_SECTORS_PER_DIRTY_CHUNK * 10000);
-    }
+    bmds->completed_sectors = cur_sector;
 
     cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);
 
@@ -194,6 +191,7 @@ static void init_blk_migration(QEMUFile *f)
     block_mig_state.submitted = 0;
     block_mig_state.read_done = 0;
     block_mig_state.transferred = 0;
+    block_mig_state.total_sector_sum = 0;
     block_mig_state.print_completion = 0;
 
     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
@@ -202,8 +200,11 @@ static void init_blk_migration(QEMUFile *f)
             bmds->bs = bs;
             bmds->bulk_completed = 0;
             bmds->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
+            bmds->completed_sectors = 0;
             bmds->shared_base = block_mig_state.shared_base;
 
+            block_mig_state.total_sector_sum += bmds->total_sectors;
+
             if (bmds->shared_base) {
                 printf("Start migration for %s with shared base image\n",
                        bs->device_name);
@@ -218,7 +219,9 @@ static void init_blk_migration(QEMUFile *f)
 
 static int blk_mig_save_bulked_block(QEMUFile *f, int is_async)
 {
+    int64_t completed_sector_sum = 0;
     BlkMigDevState *bmds;
+    int ret = 0;
 
     QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
         if (bmds->bulk_completed == 0) {
@@ -226,12 +229,23 @@ static int blk_mig_save_bulked_block(QEMUFile *f, int is_async)
                 /* completed bulk section for this device */
                 bmds->bulk_completed = 1;
             }
-            return 1;
+            completed_sector_sum += bmds->completed_sectors;
+            ret = 1;
+            break;
+        } else {
+            completed_sector_sum += bmds->completed_sectors;
         }
     }
 
-    /* we reached here means bulk is completed */
-    return 0;
+    if (completed_sector_sum >= block_mig_state.print_completion) {
+        printf("Completed %" PRId64 " %%\r",
+               completed_sector_sum * 100 / block_mig_state.total_sector_sum);
+        fflush(stdout);
+        block_mig_state.print_completion +=
+            (BDRV_SECTORS_PER_DIRTY_CHUNK * 10000);
+    }
+
+    return ret;
 }
 
 #define MAX_NUM_BLOCKS 4
@@ -319,16 +333,16 @@ static int is_stage2_completed(void)
 
 static void blk_mig_cleanup(void)
 {
-    BlkMigDevState *bmds, *next_bmds;
-    BlkMigBlock *blk, *next_blk;
+    BlkMigDevState *bmds;
+    BlkMigBlock *blk;
 
-    QTAILQ_FOREACH_SAFE(bmds, &block_mig_state.dev_list, entry, next_bmds) {
-        QTAILQ_REMOVE(&block_mig_state.dev_list, bmds, entry);
+    while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
+        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
         qemu_free(bmds);
     }
 
-    QTAILQ_FOREACH_SAFE(blk, &block_mig_state.blk_list, entry, next_blk) {
-        QTAILQ_REMOVE(&block_mig_state.blk_list, blk, entry);
+    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
+        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
         qemu_free(blk->buf);
         qemu_free(blk);
     }