Patchwork [for-1.4,2/2] block-migration: fix pending() and iterate() return values

login
register
mail settings
Submitter Stefan Hajnoczi
Date Feb. 12, 2013, 9:37 a.m.
Message ID <1360661835-28663-3-git-send-email-stefanha@redhat.com>
Download mbox | patch
Permalink /patch/219753/
State New
Headers show

Comments

Stefan Hajnoczi - Feb. 12, 2013, 9:37 a.m.
The return value of .save_live_pending() is the number of bytes
remaining.  This is just an estimate because we do not know how many
blocks will be dirtied by the running guest.

Currently our return value for .save_live_pending() is wrong because it
includes dirty blocks but not in-flight bdrv_aio_readv() requests or
unsent blocks.  Crucially, it also doesn't include the bulk phase where
the entire device is transferred - therefore we risk completing block
migration before all blocks have been transferred!

The return value of .save_live_iterate() is the number of bytes
transferred this iteration.  Currently we return whether there are bytes
remaining, which is incorrect.

Move the bytes remaining calculation into .save_live_pending() and
really return the number of bytes transferred this iteration in
.save_live_iterate().

Also fix the %ld format specifier which was used for a uint64_t
argument.  PRIu64 must be use to avoid warnings on 32-bit hosts.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block-migration.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

Patch

diff --git a/block-migration.c b/block-migration.c
index bcd0039..43ab202 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -539,6 +539,7 @@  static int block_save_setup(QEMUFile *f, void *opaque)
 static int block_save_iterate(QEMUFile *f, void *opaque)
 {
     int ret;
+    int64_t last_ftell = qemu_ftell(f);
 
     DPRINTF("Enter save live iterate submitted %d transferred %d\n",
             block_mig_state.submitted, block_mig_state.transferred);
@@ -582,12 +583,7 @@  static int block_save_iterate(QEMUFile *f, void *opaque)
 
     qemu_put_be64(f, BLK_MIG_FLAG_EOS);
 
-    /* Complete when bulk transfer is done and all dirty blocks have been
-     * transferred.
-     */
-    return block_mig_state.bulk_completed &&
-           block_mig_state.submitted == 0 &&
-           block_mig_state.read_done == 0;
+    return qemu_ftell(f) - last_ftell;
 }
 
 static int block_save_complete(QEMUFile *f, void *opaque)
@@ -629,10 +625,18 @@  static int block_save_complete(QEMUFile *f, void *opaque)
 
 static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
 {
+    /* Estimate pending number of bytes to send */
+    uint64_t pending = get_remaining_dirty() +
+                       block_mig_state.submitted * BLOCK_SIZE +
+                       block_mig_state.read_done * BLOCK_SIZE;
+
+    /* Report at least one block pending during bulk phase */
+    if (pending == 0 && !block_mig_state.bulk_completed) {
+        pending = BLOCK_SIZE;
+    }
 
-    DPRINTF("Enter save live pending  %ld\n", get_remaining_dirty());
-
-    return get_remaining_dirty();
+    DPRINTF("Enter save live pending  %" PRIu64 "\n", pending);
+    return pending;
 }
 
 static int block_load(QEMUFile *f, void *opaque, int version_id)