Signed-off-by: Md Haris Iqbal <haris.p...@gmail.com>
---
 include/migration/migration.h |  7 +++++++
 migration/migration.c         |  2 ++
 migration/ram.c               | 35 +++++++++++++++++++++++++++++++++++
 migration/savevm.c            | 19 +++++++++++++++++++
 4 files changed, 63 insertions(+)

diff --git a/include/migration/migration.h b/include/migration/migration.h
index 0a42b87..4c787ce 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -36,6 +36,7 @@
 #define QEMU_VM_CONFIGURATION        0x07
 #define QEMU_VM_COMMAND              0x08
 #define QEMU_VM_SECTION_FOOTER       0x7e
+#define QEMU_VM_ALMOST_COMPLETE      0x09
 
 struct MigrationParams {
     bool blk;
@@ -145,6 +146,11 @@ struct MigrationState
     int state;
     /* Old style params from 'migrate' command */
     MigrationParams params;
+    /*
+     * Don't need 2 variables for recovery.
+     * Clean this up, use a single variable with different states.
+     */
+    bool recovered_once;
     bool in_recovery;
 
     /* State related to return path */
@@ -360,6 +366,7 @@ int qemu_migrate_postcopy_incoming_recovery(QEMUFile 
**f,MigrationIncomingState*
 
 void migrate_incoming_ram_bitmap_init(void);
 void migrate_incoming_ram_bitmap_update(RAMBlock *rb, ram_addr_t addr);
+void *migrate_incoming_ram_req_pages(void *opaque);
 
 PostcopyState postcopy_state_get(void);
 /* Set the state and return the old state */
diff --git a/migration/migration.c b/migration/migration.c
index 99138dd..be24b69 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1042,6 +1042,7 @@ MigrationState *migrate_init(const MigrationParams 
*params)
     s->xfer_limit = 0;
     s->cleanup_bh = 0;
     s->to_dst_file = NULL;
+    s->recovered_once = false;
     s->in_recovery = false;
     s->state = MIGRATION_STATUS_NONE;
     s->params = *params;
@@ -1918,6 +1919,7 @@ static void *migration_thread(void *opaque)
                 if(ret == 0) {
                     current_active_state = MIGRATION_STATUS_POSTCOPY_ACTIVE;
                     runstate_set(RUN_STATE_FINISH_MIGRATE);
+                    s->recovered_once = true;
                     qemu_file_clear_error(s->to_dst_file);
                     continue;
                 }
diff --git a/migration/ram.c b/migration/ram.c
index 4f16243..445b863 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -2639,6 +2639,41 @@ void migrate_incoming_ram_bitmap_update(RAMBlock *rb, 
ram_addr_t addr)
     }
 }
 
+void *migrate_incoming_ram_req_pages(void* opaque)
+{
+    MigrationIncomingState *mis = opaque;
+    struct RAMBlock *rb;
+    size_t hostpagesize = getpagesize();
+    uint64_t addr;
+    unsigned long base;
+    unsigned long nr;
+    unsigned long size;
+    unsigned long next;
+    unsigned long *not_received;
+
+    not_received = atomic_rcu_read(&migration_bitmap_rcu)->not_received;
+    QLIST_FOREACH_RCU(rb, &ram_list.blocks, next) {
+        addr = 0;
+        base = rb->offset >> TARGET_PAGE_BITS;
+        size = base + (rb->used_length >> TARGET_PAGE_BITS);
+        while (true) {
+            nr = base + (addr >> TARGET_PAGE_BITS);
+            next = find_next_bit(not_received, size, nr);
+            addr = (next - base) << TARGET_PAGE_BITS;
+
+            if (addr >= rb->used_length) {
+                break;
+            }
+            else {
+                migrate_send_rp_req_pages(mis, qemu_ram_get_idstr(rb),
+                                     addr, hostpagesize);
+                addr++;
+            }
+        }
+    }
+    return NULL;
+}
+
 static SaveVMHandlers savevm_ram_handlers = {
     .save_live_setup = ram_save_setup,
     .save_live_iterate = ram_save_iterate,
diff --git a/migration/savevm.c b/migration/savevm.c
index 5fa39c1..103f0b8 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -986,6 +986,12 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f)
 {
     SaveStateEntry *se;
     int ret;
+    MigrationState* ms = migrate_get_current();
+
+    if (ms->recovered_once == true) {
+        qemu_put_byte(f, QEMU_VM_ALMOST_COMPLETE);
+        qemu_fflush(f);
+    }
 
     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
         if (!se->ops || !se->ops->save_live_complete_postcopy) {
@@ -1830,6 +1836,7 @@ static int qemu_loadvm_state_main(QEMUFile *f, 
MigrationIncomingState *mis)
     uint8_t section_type;
     int ret;
     PostcopyState ps;
+    QemuThread req_pages_not_received;
 
     while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
 
@@ -1851,6 +1858,18 @@ static int qemu_loadvm_state_main(QEMUFile *f, 
MigrationIncomingState *mis)
                 return ret;
              }
             break;
+        case QEMU_VM_ALMOST_COMPLETE:
+            /*
+             * This case will only be used when migration recovers from a
+             * network failure during a postcopy migration.
+             * Now, send the requests for pages that were lost due to the
+             * network failure.
+             */
+            qemu_thread_create(&req_pages_not_received,
+                       "postcopy/req_pages_not_received",
+                       migrate_incoming_ram_req_pages, mis,
+                       QEMU_THREAD_DETACHED);
+            break;
         default:
             error_report("Unknown savevm section type %d", section_type);
             return -EINVAL;
-- 
2.7.4


Reply via email to