Patchwork [32/35] ram: add free_space parameter to save_live functions

login
register
mail settings
Submitter Juan Quintela
Date Dec. 11, 2012, 12:47 p.m.
Message ID <1355230031-28233-33-git-send-email-quintela@redhat.com>
Download mbox | patch
Permalink /patch/205206/
State New
Headers show

Comments

Juan Quintela - Dec. 11, 2012, 12:47 p.m.
As we really know how much space we have free in the buffers, we can
send that information instead of guessing how much we can sent each time.

Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 arch_init.c       | 20 +++++++++-----------
 block-migration.c |  2 +-
 migration.c       |  3 ++-
 savevm.c          | 10 +++++++---
 sysemu.h          |  2 +-
 vmstate.h         |  2 +-
 6 files changed, 21 insertions(+), 18 deletions(-)

Patch

diff --git a/arch_init.c b/arch_init.c
index 723529a..f5f9324 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -627,9 +627,12 @@  static int ram_save_setup(QEMUFile *f, void *opaque)
     return 0;
 }

-static int ram_save_iterate(QEMUFile *f, void *opaque)
+/* Maximum size for a transmited page
+                       header + len + idstr + page size */
+#define MAX_PAGE_SIZE ( 8     + 1   +  256  + TARGET_PAGE_SIZE)
+
+static int ram_save_iterate(QEMUFile *f, void *opaque, uint64_t free_space)
 {
-    int ret;
     int i;
     int64_t t0;
     int total_sent = 0;
@@ -642,15 +645,15 @@  static int ram_save_iterate(QEMUFile *f, void *opaque)

     t0 = qemu_get_clock_ns(rt_clock);
     i = 0;
-    while ((ret = qemu_file_rate_limit(f)) == 0) {
-        int bytes_sent;
-
-        bytes_sent = ram_save_block(f, false);
+    /* We need space for at least one page and end of section marker */
+    while (free_space > MAX_PAGE_SIZE + 8) {
+        int bytes_sent = ram_save_block(f, false);
         /* no more blocks to sent */
         if (bytes_sent == 0) {
             break;
         }
         total_sent += bytes_sent;
+        free_space -= bytes_sent;
         acct_info.iterations++;
         /* we want to check in the 1st loop, just in case it was the 1st time
            and we had to sync the dirty bitmap.
@@ -668,11 +671,6 @@  static int ram_save_iterate(QEMUFile *f, void *opaque)
         i++;
     }

-    if (ret < 0) {
-        bytes_transferred += total_sent;
-        return ret;
-    }
-
     qemu_mutex_unlock_ramlist();
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
     total_sent += 8;
diff --git a/block-migration.c b/block-migration.c
index 5db01fe..b11d7e0 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -535,7 +535,7 @@  static int block_save_setup(QEMUFile *f, void *opaque)
     return 0;
 }

-static int block_save_iterate(QEMUFile *f, void *opaque)
+static int block_save_iterate(QEMUFile *f, void *opaque, uint64_t free_space)
 {
     int ret;

diff --git a/migration.c b/migration.c
index 216356d..d59f7b4 100644
--- a/migration.c
+++ b/migration.c
@@ -694,6 +694,7 @@  static void *buffered_file_thread(void *opaque)
     while (true) {
         int64_t current_time = qemu_get_clock_ms(rt_clock);
         uint64_t pending_size;
+        size_t free_space = s->buffer_capacity - s->buffer_size;

         qemu_mutex_lock_iothread();
         if (m->state != MIG_STATE_ACTIVE) {
@@ -710,7 +711,7 @@  static void *buffered_file_thread(void *opaque)
             pending_size = qemu_savevm_state_pending(m->file, max_size);
             DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
             if (pending_size && pending_size >= max_size) {
-                ret = qemu_savevm_state_iterate(m->file);
+                ret = qemu_savevm_state_iterate(m->file, free_space);
                 if (ret < 0) {
                     qemu_mutex_unlock_iothread();
                     break;
diff --git a/savevm.c b/savevm.c
index f6e91cf..4b7715a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1655,10 +1655,11 @@  int qemu_savevm_state_begin(QEMUFile *f,
  *   0 : We haven't finished, caller have to go again
  *   1 : We have finished, we can go to complete phase
  */
-int qemu_savevm_state_iterate(QEMUFile *f)
+int qemu_savevm_state_iterate(QEMUFile *f, uint64_t free_space)
 {
     SaveStateEntry *se;
     int ret = 1;
+    size_t remaining_space = free_space;

     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (!se->ops || !se->ops->save_live_iterate) {
@@ -1675,9 +1676,11 @@  int qemu_savevm_state_iterate(QEMUFile *f)
         trace_savevm_section_start();
         /* Section type */
         qemu_put_byte(f, QEMU_VM_SECTION_PART);
+        remaining_space -= 1;
         qemu_put_be32(f, se->section_id);
+        remaining_space -= 4;

-        ret = se->ops->save_live_iterate(f, se->opaque);
+        ret = se->ops->save_live_iterate(f, se->opaque, remaining_space);
         trace_savevm_section_end(se->section_id);

         if (ret <= 0) {
@@ -1687,6 +1690,7 @@  int qemu_savevm_state_iterate(QEMUFile *f)
                synchronized over and over again. */
             break;
         }
+        remaining_space -= ret;
     }
     if (ret != 0) {
         return ret;
@@ -1802,7 +1806,7 @@  static int qemu_savevm_state(QEMUFile *f)
         goto out;

     do {
-        ret = qemu_savevm_state_iterate(f);
+        ret = qemu_savevm_state_iterate(f, SIZE_MAX);
         if (ret < 0)
             goto out;
     } while (ret == 0);
diff --git a/sysemu.h b/sysemu.h
index 7832c69..7fc5124 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -75,7 +75,7 @@  void qemu_announce_self(void);
 bool qemu_savevm_state_blocked(Error **errp);
 int qemu_savevm_state_begin(QEMUFile *f,
                             const MigrationParams *params);
-int qemu_savevm_state_iterate(QEMUFile *f);
+int qemu_savevm_state_iterate(QEMUFile *f, uint64_t free_space);
 int qemu_savevm_state_complete(QEMUFile *f);
 void qemu_savevm_state_cancel(QEMUFile *f);
 uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
diff --git a/vmstate.h b/vmstate.h
index f27276c..0b55cf4 100644
--- a/vmstate.h
+++ b/vmstate.h
@@ -33,7 +33,7 @@  typedef struct SaveVMHandlers {
     void (*set_params)(const MigrationParams *params, void * opaque);
     SaveStateHandler *save_state;
     int (*save_live_setup)(QEMUFile *f, void *opaque);
-    int (*save_live_iterate)(QEMUFile *f, void *opaque);
+    int (*save_live_iterate)(QEMUFile *f, void *opaque, uint64_t free_space);
     int (*save_live_complete)(QEMUFile *f, void *opaque);
     uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
     void (*cancel)(void *opaque);