qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration
@ 2013-07-25 20:18 Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 01/12] migration: export MIG_STATE_xxx flags Lei Li
                   ` (12 more replies)
  0 siblings, 13 replies; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Hi,

This patch series tries to add localhost migration support to 
Qemu. 

When doing localhost migration, the host memory will balloon
up during the period, might consume double memories for some time.
So we want to add a new live migration mechanism localhost
migration.

Following I copied from last version that Anthony added for the 
benefit of the other reviewers:

The goal here is to allow "live upgrade" of a running QEMU instance.  
The work flow would look like this:

1) Guests are running QEMU release 1.6.1
2) Admin installs QEMU release 1.6.2 via RPM or deb
3) Admin does localhost migration with page flipping to use new version
   of QEMU.

Page flipping is used in order to avoid requiring that there is enough
free memory to fit an additional copy of the largest guest which is the
requirement today with localhost migration.

You can also read from the link below:
http://lists.gnu.org/archive/html/qemu-devel/2013-06/msg02577.html

The plan is:

1) Add new command to do localhost migration.

   The qmp interface introduced like:

   { 'command': 'localhost-migrate', 'data': {'uri': 'str'} }

2) Use different mechanism than current live migration.

   The very basic work flow like:

       qemu on the source (the source and destination are both on localhost)
              |
              V
           Stop VM
              |
              V   
          Create threads
              |
              V
       Page flipping through vmspice
              |
              V
       MADV_DONTNEED the ram pages which are already flipped
              |
              V
       Migration completes

   As stopping VM first, we expect/resume the page flipping through vmspice
   is fast enough to meet *live migration (low downtime).

Notes:
Currently the work flow is not exactly the same as description
above. For the first step, the work flow we implemented is:
stop VM and copy ram pages via unix domain socket, MADV_DONTNEED 
ram pages that already copied. After that, will replace to vmsplice
mechanism instead of copying pages.

Now it's still a draft version, and as it is implemented separately 
to the current migration code for a easy start, the next step will 
be trying to integrate it into the current migration implementation 
closely. To make sure we are on the right direction that should be 
headed, please let me know your suggestions on this.

For the interface, as Anthony has suggested using a flag or a 
capability, which one would you prefer or any ideas?

Your comments are very welcome!

TODO:
- Integrate to the current implement of migration closely?
- Introduce a mechanism to exchange a PIPE via SCM_RIGHTS.
- benchmark/evaluation.

Lei Li (12):
  migration: export MIG_STATE_xxx flags 
  savevm: export qemu_save_device_state()
  rename is_active to is_block_active
  arch_init: introduce ram_page_save()
  arch_init: introduce ram_save_local()
  arch_init: add save_local_setup to savevm_ram_handlers
  savevm: introduce qemu_savevm_local()
  savevm: adjust is_ram check in register_savevm_live()
  migration-local: implementation of outgoing part
  migration-local: implementation of incoming part
  migration-local: add option to command line for local incoming
  hmp:add hmp_localhost_migration interface

 Makefile.objs                 |    1 +
 arch_init.c                   |   110 +++++++++++++++++++
 block-migration.c             |    2 +-
 hmp-commands.hx               |   17 ++++
 hmp.c                         |   13 +++
 hmp.h                         |    1 +
 include/migration/migration.h |   32 +++++++
 include/sysemu/sysemu.h       |    1 +
 migration-local.c             |  228 +++++++++++++++++++++++++++++++++++++++++
 migration-unix.c              |   60 ++++++++++++
 migration.c                   |    8 --
 qapi-schema.json              |   14 +++
 qemu-options.hx               |    9 ++
 qmp-commands.hx               |   22 +++++
 savevm.c                      |   100 +++++++++++++++--
 vl.c                          |   14 +++
 16 files changed, 613 insertions(+), 19 deletions(-)
 create mode 100644 migration-local.c

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 01/12] migration: export MIG_STATE_xxx flags
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 02/12] savevm: export qemu_save_device_state() Lei Li
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 include/migration/migration.h |    9 +++++++++
 migration.c                   |    8 --------
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/include/migration/migration.h b/include/migration/migration.h
index e2acec6..a821c80 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -27,6 +27,15 @@ struct MigrationParams {
     bool shared;
 };
 
+/* Migration status */
+enum {
+    MIG_STATE_ERROR,      /* There has been an error. */
+    MIG_STATE_SETUP,      /* Setup stage for a migration. */
+    MIG_STATE_CANCELLED,  /* The migration has been cancelled. */
+    MIG_STATE_ACTIVE,     /* Whether the migration is active. */
+    MIG_STATE_COMPLETED,  /* The migration is successful completed. */
+};
+
 typedef struct MigrationState MigrationState;
 
 struct MigrationState
diff --git a/migration.c b/migration.c
index 058f9e6..0921ace 100644
--- a/migration.c
+++ b/migration.c
@@ -35,14 +35,6 @@
     do { } while (0)
 #endif
 
-enum {
-    MIG_STATE_ERROR,
-    MIG_STATE_SETUP,
-    MIG_STATE_CANCELLED,
-    MIG_STATE_ACTIVE,
-    MIG_STATE_COMPLETED,
-};
-
 #define MAX_THROTTLE  (32 << 20)      /* Migration speed throttling */
 
 /* Amount of time to allocate to each "chunk" of bandwidth-throttled
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 02/12] savevm: export qemu_save_device_state()
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 01/12] migration: export MIG_STATE_xxx flags Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 03/12] rename is_active to is_block_active Lei Li
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 include/sysemu/sysemu.h |    1 +
 savevm.c                |    7 ++++++-
 2 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 2fb71af..5b90027 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -80,6 +80,7 @@ int qemu_savevm_state_iterate(QEMUFile *f);
 void qemu_savevm_state_complete(QEMUFile *f);
 void qemu_savevm_state_cancel(void);
 uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
+int qemu_save_device_state(QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f);
 
 /* SLIRP */
diff --git a/savevm.c b/savevm.c
index ff5ece6..1695102 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2006,7 +2006,12 @@ static int qemu_savevm_state(QEMUFile *f)
     return ret;
 }
 
-static int qemu_save_device_state(QEMUFile *f)
+/**
+ * Save all of the device states to stream QEMUFile
+ *
+ * Return negtive if there has been an error
+ **/
+int qemu_save_device_state(QEMUFile *f)
 {
     SaveStateEntry *se;
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 03/12] rename is_active to is_block_active
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 01/12] migration: export MIG_STATE_xxx flags Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 02/12] savevm: export qemu_save_device_state() Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 04/12] arch_init: introduce ram_page_save() Lei Li
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 block-migration.c           |    2 +-
 include/migration/vmstate.h |    2 +-
 savevm.c                    |   16 ++++++++--------
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/block-migration.c b/block-migration.c
index 2fd7699..171b8b8 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -814,7 +814,7 @@ SaveVMHandlers savevm_block_handlers = {
     .save_live_pending = block_save_pending,
     .load_state = block_load,
     .cancel = block_migration_cancel,
-    .is_active = block_is_active,
+    .is_block_active = block_is_active,
 };
 
 void blk_mig_init(void)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index ebc4d09..acf847b 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -40,7 +40,7 @@ typedef struct SaveVMHandlers {
     int (*save_live_complete)(QEMUFile *f, void *opaque);
 
     /* This runs both outside and inside the iothread lock.  */
-    bool (*is_active)(void *opaque);
+    bool (*is_block_active)(void *opaque);
 
     /* This runs outside the iothread lock in the migration case, and
      * within the lock in the savevm case.  The callback had better only
diff --git a/savevm.c b/savevm.c
index 1695102..e18ca22 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1817,8 +1817,8 @@ void qemu_savevm_state_begin(QEMUFile *f,
         if (!se->ops || !se->ops->save_live_setup) {
             continue;
         }
-        if (se->ops && se->ops->is_active) {
-            if (!se->ops->is_active(se->opaque)) {
+        if (se->ops && se->ops->is_block_active) {
+            if (!se->ops->is_block_active(se->opaque)) {
                 continue;
             }
         }
@@ -1857,8 +1857,8 @@ int qemu_savevm_state_iterate(QEMUFile *f)
         if (!se->ops || !se->ops->save_live_iterate) {
             continue;
         }
-        if (se->ops && se->ops->is_active) {
-            if (!se->ops->is_active(se->opaque)) {
+        if (se->ops && se->ops->is_block_active) {
+            if (!se->ops->is_block_active(se->opaque)) {
                 continue;
             }
         }
@@ -1898,8 +1898,8 @@ void qemu_savevm_state_complete(QEMUFile *f)
         if (!se->ops || !se->ops->save_live_complete) {
             continue;
         }
-        if (se->ops && se->ops->is_active) {
-            if (!se->ops->is_active(se->opaque)) {
+        if (se->ops && se->ops->is_block_active) {
+            if (!se->ops->is_block_active(se->opaque)) {
                 continue;
             }
         }
@@ -1952,8 +1952,8 @@ uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
         if (!se->ops || !se->ops->save_live_pending) {
             continue;
         }
-        if (se->ops && se->ops->is_active) {
-            if (!se->ops->is_active(se->opaque)) {
+        if (se->ops && se->ops->is_block_active) {
+            if (!se->ops->is_block_active(se->opaque)) {
                 continue;
             }
         }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 04/12] arch_init: introduce ram_page_save()
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (2 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 03/12] rename is_active to is_block_active Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-08-02 19:40   ` Michael R. Hines
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 05/12] arch_init: introduce ram_save_local() Lei Li
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 arch_init.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index a8b91ee..a418071 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -699,6 +699,64 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
     return remaining_size;
 }
 
+/* This is the last block from where we have sent data for local migration */
+static RAMBlock *last_block_local;
+static ram_addr_t last_offset_local;
+
+static int ram_page_save(QEMUFile *f)
+{
+    RAMBlock *block = last_block_local;
+    ram_addr_t offset = last_offset_local;
+    MemoryRegion *mr = block->mr;
+    int bytes_sent = 0;
+
+    if (!block) {
+        block = QTAILQ_FIRST(&ram_list.blocks);
+    }
+
+    do {
+        mr = block->mr;
+        uint8_t *p;
+        int cont = (block == last_block_local) ? RAM_SAVE_FLAG_CONTINUE : 0;
+
+        p = memory_region_get_ram_ptr(mr) + offset;
+
+        if (is_zero_page(p)) {
+            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
+            if (!cont) {
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
+            }
+            qemu_put_byte(f, *p);
+            bytes_sent = 1;
+        } else {
+            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
+            if (!cont) {
+                qemu_put_byte(f, strlen(block->idstr));
+                qemu_put_buffer(f, (uint8_t *)block->idstr,
+                                strlen(block->idstr));
+            }
+            qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
+            bytes_sent = TARGET_PAGE_SIZE;
+        }
+
+        offset += TARGET_PAGE_SIZE;
+        if (offset >= block->length) {
+            offset = 0;
+            block = QTAILQ_NEXT(block, next);
+            if (!block) {
+                block = QTAILQ_FIRST(&ram_list.blocks);
+            }
+        }
+    } while (block != last_block_local || offset != last_offset_local);
+
+    last_block_local = block;
+    last_offset_local = offset;
+
+    return bytes_sent;
+}
+
 static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
 {
     int ret, rc = 0;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 05/12] arch_init: introduce ram_save_local()
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (3 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 04/12] arch_init: introduce ram_page_save() Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-08-02 19:42   ` Michael R. Hines
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 06/12] arch_init: add save_local_setup to savevm_ram_handlers Lei Li
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 arch_init.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index a418071..7eeb52f 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -757,6 +757,38 @@ static int ram_page_save(QEMUFile *f)
     return bytes_sent;
 }
 
+static int ram_save_local(QEMUFile *f, void *opaque)
+{
+    uint64_t bytes_sent = 0;
+    uint64_t total_ram_bytes = ram_bytes_total();
+
+    qemu_mutex_lock_ramlist();
+
+    while (total_ram_bytes) {
+       void *ram;
+       MemoryRegion *mr;
+
+       bytes_sent = ram_page_save(f);
+       /* No more ram pages. */
+       if (bytes_sent == 0) {
+           return bytes_sent;
+       }
+
+       mr = last_block_local->mr;
+       ram = memory_region_get_ram_ptr(mr) + last_offset_local;
+
+       /* DONTNEED the ram page that has already copied. */
+       qemu_madvise(ram, bytes_sent, QEMU_MADV_DONTNEED);
+       total_ram_bytes -= bytes_sent;
+    }
+
+    qemu_mutex_unlock_ramlist();
+
+    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
+
+    return bytes_sent;
+}
+
 static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
 {
     int ret, rc = 0;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 06/12] arch_init: add save_local_setup to savevm_ram_handlers
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (4 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 05/12] arch_init: introduce ram_save_local() Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-08-02 19:43   ` Michael R. Hines
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 07/12] savevm: introduce qemu_savevm_local() Lei Li
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 arch_init.c                 |    1 +
 include/migration/vmstate.h |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 7eeb52f..5c25005 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -973,6 +973,7 @@ SaveVMHandlers savevm_ram_handlers = {
     .save_live_iterate = ram_save_iterate,
     .save_live_complete = ram_save_complete,
     .save_live_pending = ram_save_pending,
+    .save_local_setup = ram_save_local,
     .load_state = ram_load,
     .cancel = ram_migration_cancel,
 };
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index acf847b..c534254 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -53,6 +53,8 @@ typedef struct SaveVMHandlers {
     int (*save_live_setup)(QEMUFile *f, void *opaque);
     uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
 
+    int (*save_local_setup)(QEMUFile *f, void *opaque);
+
     LoadStateHandler *load_state;
 } SaveVMHandlers;
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 07/12] savevm: introduce qemu_savevm_local()
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (5 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 06/12] arch_init: add save_local_setup to savevm_ram_handlers Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-08-02 19:48   ` Michael R. Hines
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 08/12] savevm: adjust is_ram check in register_savevm_live() Lei Li
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 include/sysemu/sysemu.h |    1 +
 savevm.c                |   55 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 5b90027..9abe4c9 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -80,6 +80,7 @@ int qemu_savevm_state_iterate(QEMUFile *f);
 void qemu_savevm_state_complete(QEMUFile *f);
 void qemu_savevm_state_cancel(void);
 uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
+int qemu_savevm_local(QEMUFile *f);
 int qemu_save_device_state(QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f);
 
diff --git a/savevm.c b/savevm.c
index e18ca22..c183369 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2007,6 +2007,61 @@ static int qemu_savevm_state(QEMUFile *f)
 }
 
 /**
+ * Save all of the ram pages to stream QEMUFile
+ *
+ * Return: negtive for an error
+ */
+int qemu_savevm_local(QEMUFile *f)
+{
+    SaveStateEntry *se;
+    int ret;
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if (!se->ops) {
+            continue;
+        }
+    }
+
+    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
+    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        int len;
+
+        if (!se->ops || !se->ops->save_local_setup) {
+            continue;
+        }
+        if (se->ops && se->ops->is_block_active) {
+            continue;
+        }
+
+        /* Section type */
+        qemu_put_byte(f, QEMU_VM_SECTION_START);
+        qemu_put_be32(f, se->section_id);
+
+        /* ID string */
+        len = strlen(se->idstr);
+        qemu_put_byte(f, len);
+        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
+
+        qemu_put_be32(f, se->instance_id);
+
+        qemu_put_be32(f, se->version_id);
+
+        ret = se->ops->save_local_setup(f, se->opaque);
+        if (ret < 0) {
+            qemu_file_set_error(f, ret);
+            break;
+        }
+    }
+
+    qemu_put_byte(f, QEMU_VM_EOF);
+    qemu_fflush(f);
+
+    return qemu_file_get_error(f);
+}
+
+/**
  * Save all of the device states to stream QEMUFile
  *
  * Return negtive if there has been an error
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 08/12] savevm: adjust is_ram check in register_savevm_live()
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (6 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 07/12] savevm: introduce qemu_savevm_local() Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 09/12] migration-local: implementation of outgoing part Lei Li
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 savevm.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/savevm.c b/savevm.c
index c183369..e826f64 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1484,7 +1484,8 @@ int register_savevm_live(DeviceState *dev,
     se->vmsd = NULL;
     se->no_migrate = 0;
     /* if this is a live_savem then set is_ram */
-    if (ops->save_live_setup != NULL) {
+    if ((ops->save_live_setup != NULL)
+         || (ops->save_local_setup != NULL)) {
         se->is_ram = 1;
     }
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 09/12] migration-local: implementation of outgoing part
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (7 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 08/12] savevm: adjust is_ram check in register_savevm_live() Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-08-02 19:45   ` Michael R. Hines
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 10/12] migration-local: implementation of incoming part Lei Li
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 Makefile.objs                 |    1 +
 include/migration/migration.h |   15 ++++
 migration-local.c             |  158 +++++++++++++++++++++++++++++++++++++++++
 migration-unix.c              |   13 ++++
 qapi-schema.json              |   14 ++++
 qmp-commands.hx               |   22 ++++++
 6 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100644 migration-local.c

diff --git a/Makefile.objs b/Makefile.objs
index 5b288ba..2a3d9a5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -53,6 +53,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
 common-obj-y += migration.o migration-tcp.o
 common-obj-y += qemu-char.o #aio.o
 common-obj-y += block-migration.o
+common-obj-y += migration-local.o
 common-obj-y += page_cache.o xbzrle.o
 
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
diff --git a/include/migration/migration.h b/include/migration/migration.h
index a821c80..a690e18 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -58,6 +58,17 @@ struct MigrationState
     int64_t xbzrle_cache_size;
 };
 
+
+typedef struct LocalMigState LocalMigState;
+
+struct LocalMigState
+{
+    int fd;
+    int state;
+    QEMUFile *file;
+    QemuThread thread;
+};
+
 void process_incoming_migration(QEMUFile *f);
 
 void qemu_start_incoming_migration(const char *uri, Error **errp);
@@ -80,6 +91,8 @@ void unix_start_incoming_migration(const char *path, Error **errp);
 
 void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp);
 
+void unix_start_local_outgoing_migration(LocalMigState *s, const char *path, Error **errp);
+
 void fd_start_incoming_migration(const char *path, Error **errp);
 
 void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp);
@@ -88,6 +101,8 @@ void migrate_fd_error(MigrationState *s);
 
 void migrate_fd_connect(MigrationState *s);
 
+void local_migration_fd_connect(LocalMigState *s);
+
 int migrate_fd_close(MigrationState *s);
 
 void add_migration_state_change_notifier(Notifier *notify);
diff --git a/migration-local.c b/migration-local.c
new file mode 100644
index 0000000..5bd1ed0
--- /dev/null
+++ b/migration-local.c
@@ -0,0 +1,158 @@
+/*
+ * QEMU localhost migration
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions are licensed under the terms of the GNU GPL, version 2
+ * or (at your option) any later version.
+ */
+
+#include "qemu-common.h"
+#include "migration/migration.h"
+#include "monitor/monitor.h"
+#include "migration/qemu-file.h"
+#include "sysemu/sysemu.h"
+#include "block/block.h"
+#include "qemu/sockets.h"
+#include "migration/block.h"
+#include "qemu/thread.h"
+#include "qmp-commands.h"
+#include "exec/memory.h"
+#include "trace.h"
+#include "qemu/osdep.h"
+
+//#define DEBUG_MIGRATION_LOCAL
+
+#ifdef DEBUG_MIGRATION_LOCAL
+#define DPRINTF(fmt, ...) \
+    do { printf("migration-local: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+
+/************************************************************************
+ * Outgoing part
+ */
+
+static LocalMigState *local_migration_init(void)
+{
+    LocalMigState *s = g_malloc0(sizeof(*s));
+
+    s->state = MIG_STATE_SETUP;
+    trace_migrate_set_state(MIG_STATE_SETUP);
+    s->fd = -1;
+
+    return s;
+}
+
+static void local_migration_error(LocalMigState *s)
+{
+    assert(s->file == NULL);
+
+    s->state = MIG_STATE_ERROR;
+    trace_migrate_set_state(MIG_STATE_ERROR);
+}
+
+static void local_outgoing_completed(LocalMigState *s)
+{
+    s->state = MIG_STATE_COMPLETED;
+    trace_migrate_set_state(MIG_STATE_COMPLETED);
+}
+
+static void *migration_local_thread(void *opaque)
+{
+    LocalMigState *s = opaque;
+    int ret;
+
+    DPRINTF("Beginning savevm\n");
+
+    while (s->state == MIG_STATE_ACTIVE) {
+        qemu_mutex_lock_iothread();
+        ret = qemu_savevm_local(s->file);
+        qemu_mutex_unlock_iothread();
+
+        /* No need to send device states if ram pages fails to to sent. */
+        if (ret < 0) {
+            local_migration_error(s);
+            break;
+        }
+
+        qemu_save_device_state(s->file);
+        qemu_fclose(s->file);
+    }
+
+    ret = qemu_file_get_error(s->file);
+    if (ret < 0) {
+        local_migration_error(s);
+    } else {
+        local_outgoing_completed(s);
+    }
+
+    qemu_mutex_lock_iothread();
+
+    if (s->state == MIG_STATE_COMPLETED) {
+        runstate_set(RUN_STATE_POSTMIGRATE);
+    }
+
+    qemu_mutex_unlock_iothread();
+
+    return NULL;
+}
+
+void local_migration_fd_connect(LocalMigState *s)
+{
+    s->state = MIG_STATE_ACTIVE;
+    trace_migrate_set_state(MIG_STATE_ACTIVE);
+
+    qemu_thread_create(&s->thread, migration_local_thread, s,
+                       QEMU_THREAD_JOINABLE);
+}
+
+void qmp_localhost_migrate(const char *uri, Error **errp)
+{
+    const char *path;
+    Error *local_err = NULL;
+    int is_vm_running;
+    LocalMigState *s;
+
+    if (qemu_savevm_state_blocked(errp)) {
+        return;
+    }
+
+    s = local_migration_init();
+    bdrv_flush_all();
+
+    is_vm_running = runstate_is_running();
+
+    /* Stop the VM first */
+    if (is_vm_running) {
+        vm_stop(RUN_STATE_SAVE_VM);
+    }
+
+    /* Start outgoing migration by unix socket. */
+    if (strstart(uri, "unix:", &path)) {
+        /* XXX. Creat a new unix_start_outgoing_migration_* is not necessary,
+         * just for the first step. This will be replaced by vmsplice
+         * mechanism. */
+        unix_start_local_outgoing_migration(s, path, &local_err);
+    } else {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
+        goto fail;
+    }
+
+    if (local_err) {
+        s->state = MIG_STATE_ERROR;
+        error_propagate(errp, local_err);
+        goto fail;
+    }
+
+fail:
+    if (!is_vm_running) {
+        vm_start();
+    }
+}
diff --git a/migration-unix.c b/migration-unix.c
index 94b7022..ec20c45 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -49,6 +49,19 @@ void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **
     unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
 }
 
+void unix_start_local_outgoing_migration(LocalMigState *s, const char *path, Error **errp)
+{
+    s->fd = unix_connect(path, errp);
+    if (s->fd < 0) {
+        s->file = NULL;
+        /* There should be a fd_error_set function */
+        s->state = MIG_STATE_ERROR;
+    } else {
+        s->file = qemu_fopen_socket(s->fd, "wb");
+        local_migration_fd_connect(s);
+    }
+}
+
 static void unix_accept_incoming_migration(void *opaque)
 {
     struct sockaddr_un addr;
diff --git a/qapi-schema.json b/qapi-schema.json
index a80ee40..7431a41 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2336,6 +2336,20 @@
 { 'command': 'migrate',
   'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }
 
+##
+# @localhost-migrate
+#
+# Migrates the current running guest to the localhost VM.
+#
+# @uri: the Uniform Resource Identifier of the destination VM
+#
+# Returns: nothing on success
+#
+# Since: 1.7
+##
+{ 'command': 'localhost-migrate',
+  'data': {'uri': 'str'} }
+
 # @xen-save-devices-state:
 #
 # Save the state of all devices to file. The RAM and the block devices
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 8cea5e5..aba2327 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -640,6 +640,28 @@ Notes:
 EQMP
 
     {
+        .name      = "localhost-migrate",
+        .args_type = "uri:s",
+        .mhandler.cmd_new = qmp_marshal_input_localhost_migrate,
+    },
+
+SQMP
+localhost-migrate
+
+Migrate VM in localhost.
+
+Arguments:
+
+- "uri": Destination URI (json-string)
+
+Example:
+
+-> { "execute": "localhost-migrate", "arguments": { "uri": "UNIX-SOCKET" }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "migrate_cancel",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_migrate_cancel,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 10/12] migration-local: implementation of incoming part
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (8 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 09/12] migration-local: implementation of outgoing part Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 11/12] migration-local: add option to commandline for incoming-local Lei Li
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 include/migration/migration.h |    6 +++++
 migration-local.c             |   39 ++++++++++++++++++++++++++++++++++
 migration-unix.c              |   47 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/include/migration/migration.h b/include/migration/migration.h
index a690e18..5e7416f 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -73,6 +73,10 @@ void process_incoming_migration(QEMUFile *f);
 
 void qemu_start_incoming_migration(const char *uri, Error **errp);
 
+void start_local_incoming_migration(QEMUFile *f);
+
+void qemu_start_local_incoming_migration(const char *uri, Error **errp);
+
 uint64_t migrate_max_downtime(void);
 
 void do_info_migrate_print(Monitor *mon, const QObject *data);
@@ -89,6 +93,8 @@ void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Erro
 
 void unix_start_incoming_migration(const char *path, Error **errp);
 
+void unix_start_local_incoming_migration(const char *path, Error **errp);
+
 void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp);
 
 void unix_start_local_outgoing_migration(LocalMigState *s, const char *path, Error **errp);
diff --git a/migration-local.c b/migration-local.c
index 5bd1ed0..479b796 100644
--- a/migration-local.c
+++ b/migration-local.c
@@ -156,3 +156,42 @@ fail:
         vm_start();
     }
 }
+
+/**********************************************************************
+ * Incoming part
+ */
+
+void qemu_start_local_incoming_migration(const char *uri, Error **errp)
+{
+    const char *p;
+
+    if (strstart(uri, "unix:", &p)) {
+        unix_start_local_incoming_migration(p, errp);
+    } else {
+        error_setg(errp, "unknown migration protocol: %s", uri);
+    }
+}
+
+void start_local_incoming_migration(QEMUFile *f)
+{
+    int ret;
+
+    ret = qemu_loadvm_state(f);
+    if (ret < 0) {
+        fprintf(stderr, "load of migration failed\n");
+        exit(EXIT_FAILURE);
+    }
+    qemu_announce_self();
+
+    DPRINTF("successfully loaded vm state\n");
+
+    bdrv_clear_incoming_migration_all();
+    /* Make sure all file formats flush their mutable metadata */
+    bdrv_invalidate_cache_all();
+
+    if (autostart) {
+        vm_start();
+    } else {
+        runstate_set(RUN_STATE_PAUSED);
+    }
+}
diff --git a/migration-unix.c b/migration-unix.c
index ec20c45..70c847a 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -108,3 +108,50 @@ void unix_start_incoming_migration(const char *path, Error **errp)
     qemu_set_fd_handler2(s, NULL, unix_accept_incoming_migration, NULL,
                          (void *)(intptr_t)s);
 }
+
+static void unix_accept_local_incoming_migration(void *opaque)
+{
+    struct sockaddr_un addr;
+    socklen_t addrlen = sizeof(addr);
+    int s = (intptr_t)opaque;
+    QEMUFile *f;
+    int c;
+
+    do {
+        c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
+    } while (c == -1 && errno == EINTR);
+    qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
+    close(s);
+
+    DPRINTF("accepted migration\n");
+
+    if (c == -1) {
+        fprintf(stderr, "could not accept migration connection\n");
+        goto out;
+    }
+
+    f = qemu_fopen_socket(c, "rb");
+    if (f == NULL) {
+        fprintf(stderr, "could not qemu_fopen socket\n");
+        goto out;
+    }
+
+    start_local_incoming_migration(f);
+    return;
+
+out:
+    close(c);
+}
+
+void unix_start_local_incoming_migration(const char *path, Error **errp)
+{
+    int ret;
+
+    ret = unix_listen(path, NULL, 0, errp);
+    if (ret < 0) {
+        return;
+    }
+
+    qemu_set_fd_handler2(ret, NULL, unix_accept_local_incoming_migration, NULL,
+                         (void *)(intptr_t)ret);
+}
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 11/12] migration-local: add option to commandline for incoming-local
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (9 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 10/12] migration-local: implementation of incoming part Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-08-02 19:46   ` Michael R. Hines
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 12/12] hmp: add hmp_localhost_migration interface Lei Li
  2013-07-26  9:41 ` [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Paolo Bonzini
  12 siblings, 1 reply; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 qemu-options.hx |    9 +++++++++
 vl.c            |   14 ++++++++++++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 8355f9b..a975e83 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2912,6 +2912,15 @@ STEXI
 Prepare for incoming migration, listen on @var{port}.
 ETEXI
 
+DEF("incoming-local", HAS_ARG, QEMU_OPTION_incoming_local, \
+    "-incoming-local p prepare for localhost incoming migration, listen on domain unix socket p\n",
+    QEMU_ARCH_ALL)
+STEXI
+@item -incoming-local @var{port}
+@findex -incoming-local
+Prepare for localhost incoming migration, listen on @var{port}
+ETEXI
+
 DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
     "-nodefaults     don't create default devices\n", QEMU_ARCH_ALL)
 STEXI
diff --git a/vl.c b/vl.c
index 767e020..b820db5 100644
--- a/vl.c
+++ b/vl.c
@@ -2854,6 +2854,7 @@ int main(int argc, char **argv, char **envp)
     const char *vga_model = "none";
     const char *pid_file = NULL;
     const char *incoming = NULL;
+    const char *incoming_local = NULL;
 #ifdef CONFIG_VNC
     int show_vnc_port = 0;
 #endif
@@ -3691,6 +3692,10 @@ int main(int argc, char **argv, char **envp)
                 incoming = optarg;
                 runstate_set(RUN_STATE_INMIGRATE);
                 break;
+            case QEMU_OPTION_incoming_local:
+                incoming_local = optarg;
+                runstate_set(RUN_STATE_INMIGRATE);
+                break;
             case QEMU_OPTION_nodefaults:
                 default_serial = 0;
                 default_parallel = 0;
@@ -4377,6 +4382,15 @@ int main(int argc, char **argv, char **envp)
             error_free(local_err);
             exit(1);
         }
+    } else if (incoming_local) {
+        Error *local_err = NULL;
+        qemu_start_local_incoming_migration(incoming_local, &local_err);
+        if (local_err) {
+            fprintf(stderr, "-incoming_local %s: %s\n", incoming_local,
+                    error_get_pretty(local_err));
+            error_free(local_err);
+            exit(1);
+        }
     } else if (autostart) {
         vm_start();
     }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 12/12] hmp: add hmp_localhost_migration interface
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (10 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 11/12] migration-local: add option to commandline for incoming-local Lei Li
@ 2013-07-25 20:18 ` Lei Li
  2013-08-02 19:47   ` Michael R. Hines
  2013-07-26  9:41 ` [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Paolo Bonzini
  12 siblings, 1 reply; 28+ messages in thread
From: Lei Li @ 2013-07-25 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: aarcange, aliguori, Lei Li, quintela, lagarcia, pbonzini, rcj

Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
---
 hmp-commands.hx |   17 +++++++++++++++++
 hmp.c           |   13 +++++++++++++
 hmp.h           |    1 +
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 915b0d1..ed21970 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -989,6 +989,23 @@ STEXI
 Set the spice/vnc connection info for the migration target.  The spice/vnc
 server will ask the spice/vnc client to automatically reconnect using the
 new parameters (if specified) once the vm migration finished successfully.
+
+ETEXI
+
+    {
+        .name       = "localhost_migrate",
+        .args_type  = "uri:s",
+        .params     = "uri",
+        .help       = "migrate to domain socket URI on localhost",
+        .mhandler.cmd = hmp_localhost_migrate,
+    },
+
+
+STEXI
+@item localhost_migrate @var{uri}
+@findex localhost_migrate
+Migrate to @var{uri}.
+
 ETEXI
 
     {
diff --git a/hmp.c b/hmp.c
index 494a9aa..a7e779f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1191,6 +1191,19 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
     }
 }
 
+void hmp_localhost_migrate(Monitor *mon, const QDict *qdict)
+{
+    const char *uri = qdict_get_str(qdict, "uri");
+    Error *errp = NULL;
+
+    qmp_localhost_migrate(uri, &errp);
+    if (errp) {
+        monitor_printf(mon, "local_migrate: %s\n", error_get_pretty(errp));
+        error_free(errp);
+        return;
+    }
+}
+
 void hmp_device_del(Monitor *mon, const QDict *qdict)
 {
     const char *id = qdict_get_str(qdict, "id");
diff --git a/hmp.h b/hmp.h
index 56d2e92..9124c0e 100644
--- a/hmp.h
+++ b/hmp.h
@@ -60,6 +60,7 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
+void hmp_localhost_migrate(Monitor *mon, const QDict *qdict);
 void hmp_set_password(Monitor *mon, const QDict *qdict);
 void hmp_expire_password(Monitor *mon, const QDict *qdict);
 void hmp_eject(Monitor *mon, const QDict *qdict);
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration
  2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
                   ` (11 preceding siblings ...)
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 12/12] hmp: add hmp_localhost_migration interface Lei Li
@ 2013-07-26  9:41 ` Paolo Bonzini
  2013-08-05  8:56   ` Lei Li
  12 siblings, 1 reply; 28+ messages in thread
From: Paolo Bonzini @ 2013-07-26  9:41 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, rcj

Il 25/07/2013 22:18, Lei Li ha scritto:
> Hi,
> 
> This patch series tries to add localhost migration support to 
> Qemu. 
> 
> When doing localhost migration, the host memory will balloon
> up during the period, might consume double memories for some time.
> So we want to add a new live migration mechanism localhost
> migration.
> 
> Following I copied from last version that Anthony added for the 
> benefit of the other reviewers:
> 
> The goal here is to allow "live upgrade" of a running QEMU instance.  
> The work flow would look like this:
> 
> 1) Guests are running QEMU release 1.6.1
> 2) Admin installs QEMU release 1.6.2 via RPM or deb
> 3) Admin does localhost migration with page flipping to use new version
>    of QEMU.
> 
> Page flipping is used in order to avoid requiring that there is enough
> free memory to fit an additional copy of the largest guest which is the
> requirement today with localhost migration.
> 
> You can also read from the link below:
> http://lists.gnu.org/archive/html/qemu-devel/2013-06/msg02577.html
> 
> The plan is:
> 
> 1) Add new command to do localhost migration.
> 
>    The qmp interface introduced like:
> 
>    { 'command': 'localhost-migrate', 'data': {'uri': 'str'} }
> 
> 2) Use different mechanism than current live migration.
> 
>    The very basic work flow like:
> 
>        qemu on the source (the source and destination are both on localhost)
>               |
>               V
>            Stop VM
>               |
>               V   
>           Create threads
>               |
>               V
>        Page flipping through vmspice
>               |
>               V
>        MADV_DONTNEED the ram pages which are already flipped
>               |
>               V
>        Migration completes
> 
>    As stopping VM first, we expect/resume the page flipping through vmspice
>    is fast enough to meet *live migration (low downtime).
> 
> Notes:
> Currently the work flow is not exactly the same as description
> above. For the first step, the work flow we implemented is:
> stop VM and copy ram pages via unix domain socket, MADV_DONTNEED 
> ram pages that already copied. After that, will replace to vmsplice
> mechanism instead of copying pages.
> 
> Now it's still a draft version, and as it is implemented separately 
> to the current migration code for a easy start, the next step will 
> be trying to integrate it into the current migration implementation 
> closely. To make sure we are on the right direction that should be 
> headed, please let me know your suggestions on this.
> 
> For the interface, as Anthony has suggested using a flag or a 
> capability, which one would you prefer or any ideas?

Using a capability on the source makes sense; I don't think anything
special is needed on the destination.  The destination just sees a
special packet telling it that a pipe is available via SCM_RIGHTS; then
it fetches the file descriptor and uses it for the new protocol.

It looks like this could reuse a lot of the RAM copying hooks that we
introduced for RDMA.  You shouldn't need to change anything in savevm.c
or arch_init.c

Paolo

> Your comments are very welcome!
> 
> TODO:
> - Integrate to the current implement of migration closely?
> - Introduce a mechanism to exchange a PIPE via SCM_RIGHTS.
> - benchmark/evaluation.
> 
> Lei Li (12):
>   migration: export MIG_STATE_xxx flags 
>   savevm: export qemu_save_device_state()
>   rename is_active to is_block_active
>   arch_init: introduce ram_page_save()
>   arch_init: introduce ram_save_local()
>   arch_init: add save_local_setup to savevm_ram_handlers
>   savevm: introduce qemu_savevm_local()
>   savevm: adjust is_ram check in register_savevm_live()
>   migration-local: implementation of outgoing part
>   migration-local: implementation of incoming part
>   migration-local: add option to command line for local incoming
>   hmp:add hmp_localhost_migration interface
> 
>  Makefile.objs                 |    1 +
>  arch_init.c                   |   110 +++++++++++++++++++
>  block-migration.c             |    2 +-
>  hmp-commands.hx               |   17 ++++
>  hmp.c                         |   13 +++
>  hmp.h                         |    1 +
>  include/migration/migration.h |   32 +++++++
>  include/sysemu/sysemu.h       |    1 +
>  migration-local.c             |  228 +++++++++++++++++++++++++++++++++++++++++
>  migration-unix.c              |   60 ++++++++++++
>  migration.c                   |    8 --
>  qapi-schema.json              |   14 +++
>  qemu-options.hx               |    9 ++
>  qmp-commands.hx               |   22 +++++
>  savevm.c                      |   100 +++++++++++++++--
>  vl.c                          |   14 +++
>  16 files changed, 613 insertions(+), 19 deletions(-)
>  create mode 100644 migration-local.c
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/12] arch_init: introduce ram_page_save()
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 04/12] arch_init: introduce ram_page_save() Lei Li
@ 2013-08-02 19:40   ` Michael R. Hines
  2013-08-05  2:49     ` Lei Li
  0 siblings, 1 reply; 28+ messages in thread
From: Michael R. Hines @ 2013-08-02 19:40 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   arch_init.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 files changed, 58 insertions(+), 0 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index a8b91ee..a418071 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -699,6 +699,64 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
>       return remaining_size;
>   }
>
> +/* This is the last block from where we have sent data for local migration */
> +static RAMBlock *last_block_local;
> +static ram_addr_t last_offset_local;
> +
> +static int ram_page_save(QEMUFile *f)
> +{
> +    RAMBlock *block = last_block_local;
> +    ram_addr_t offset = last_offset_local;
> +    MemoryRegion *mr = block->mr;
> +    int bytes_sent = 0;
> +
> +    if (!block) {
> +        block = QTAILQ_FIRST(&ram_list.blocks);
> +    }
> +
> +    do {
> +        mr = block->mr;
> +        uint8_t *p;
> +        int cont = (block == last_block_local) ? RAM_SAVE_FLAG_CONTINUE : 0;
> +
> +        p = memory_region_get_ram_ptr(mr) + offset;
> +
> +        if (is_zero_page(p)) {
> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
> +            if (!cont) {
> +                qemu_put_byte(f, strlen(block->idstr));
> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
> +                                strlen(block->idstr));
> +            }
> +            qemu_put_byte(f, *p);
> +            bytes_sent = 1;
> +        } else {
> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
> +            if (!cont) {
> +                qemu_put_byte(f, strlen(block->idstr));
> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
> +                                strlen(block->idstr));
> +            }
> +            qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
> +            bytes_sent = TARGET_PAGE_SIZE;
> +        }
> +
> +        offset += TARGET_PAGE_SIZE;
> +        if (offset >= block->length) {
> +            offset = 0;
> +            block = QTAILQ_NEXT(block, next);
> +            if (!block) {
> +                block = QTAILQ_FIRST(&ram_list.blocks);
> +            }
> +        }
> +    } while (block != last_block_local || offset != last_offset_local);
> +
> +    last_block_local = block;
> +    last_offset_local = offset;
> +
> +    return bytes_sent;
> +}
> +
>   static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
>   {
>       int ret, rc = 0;

Seems like there's a lot of duplicate code.

We have new hooks to override the way memory is saved in arch_init.c

See the QEMUFileOps......... save_page() / before_ram_iterate() / 
after_ram_iterate()

You might need to introduce a new "load_page()" pointer in QEMUFileOps.

Then all this code can be private to migration-local.c

- Michael

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 05/12] arch_init: introduce ram_save_local()
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 05/12] arch_init: introduce ram_save_local() Lei Li
@ 2013-08-02 19:42   ` Michael R. Hines
  2013-08-05  3:27     ` Lei Li
  0 siblings, 1 reply; 28+ messages in thread
From: Michael R. Hines @ 2013-08-02 19:42 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   arch_init.c |   32 ++++++++++++++++++++++++++++++++
>   1 files changed, 32 insertions(+), 0 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index a418071..7eeb52f 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -757,6 +757,38 @@ static int ram_page_save(QEMUFile *f)
>       return bytes_sent;
>   }
>
> +static int ram_save_local(QEMUFile *f, void *opaque)
> +{
> +    uint64_t bytes_sent = 0;
> +    uint64_t total_ram_bytes = ram_bytes_total();
> +
> +    qemu_mutex_lock_ramlist();
> +
> +    while (total_ram_bytes) {
> +       void *ram;
> +       MemoryRegion *mr;
> +
> +       bytes_sent = ram_page_save(f);
> +       /* No more ram pages. */
> +       if (bytes_sent == 0) {
> +           return bytes_sent;
> +       }
> +
> +       mr = last_block_local->mr;
> +       ram = memory_region_get_ram_ptr(mr) + last_offset_local;
> +
> +       /* DONTNEED the ram page that has already copied. */
> +       qemu_madvise(ram, bytes_sent, QEMU_MADV_DONTNEED);
> +       total_ram_bytes -= bytes_sent;
> +    }
> +
> +    qemu_mutex_unlock_ramlist();
> +
> +    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
> +
> +    return bytes_sent;
> +}
> +
>   static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
>   {
>       int ret, rc = 0;

You need to create a new private structure "QEMUFileLocal".

Then override f->save_page and point this to your own function.

See migration-rdma.c for an example.

- Michael

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 06/12] arch_init: add save_local_setup to savevm_ram_handlers
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 06/12] arch_init: add save_local_setup to savevm_ram_handlers Lei Li
@ 2013-08-02 19:43   ` Michael R. Hines
  0 siblings, 0 replies; 28+ messages in thread
From: Michael R. Hines @ 2013-08-02 19:43 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   arch_init.c                 |    1 +
>   include/migration/vmstate.h |    2 ++
>   2 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index 7eeb52f..5c25005 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -973,6 +973,7 @@ SaveVMHandlers savevm_ram_handlers = {
>       .save_live_iterate = ram_save_iterate,
>       .save_live_complete = ram_save_complete,
>       .save_live_pending = ram_save_pending,
> +    .save_local_setup = ram_save_local,
>       .load_state = ram_load,
>       .cancel = ram_migration_cancel,
>   };
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index acf847b..c534254 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -53,6 +53,8 @@ typedef struct SaveVMHandlers {
>       int (*save_live_setup)(QEMUFile *f, void *opaque);
>       uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
>
> +    int (*save_local_setup)(QEMUFile *f, void *opaque);
> +
>       LoadStateHandler *load_state;
>   } SaveVMHandlers;
>

save_page() should be good enough for you - it has more parameters too 
.... see last email....

- Michael

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 09/12] migration-local: implementation of outgoing part
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 09/12] migration-local: implementation of outgoing part Lei Li
@ 2013-08-02 19:45   ` Michael R. Hines
  2013-08-05  3:18     ` Lei Li
  0 siblings, 1 reply; 28+ messages in thread
From: Michael R. Hines @ 2013-08-02 19:45 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   Makefile.objs                 |    1 +
>   include/migration/migration.h |   15 ++++
>   migration-local.c             |  158 +++++++++++++++++++++++++++++++++++++++++
>   migration-unix.c              |   13 ++++
>   qapi-schema.json              |   14 ++++
>   qmp-commands.hx               |   22 ++++++
>   6 files changed, 223 insertions(+), 0 deletions(-)
>   create mode 100644 migration-local.c
>
> diff --git a/Makefile.objs b/Makefile.objs
> index 5b288ba..2a3d9a5 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -53,6 +53,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
>   common-obj-y += migration.o migration-tcp.o
>   common-obj-y += qemu-char.o #aio.o
>   common-obj-y += block-migration.o
> +common-obj-y += migration-local.o
>   common-obj-y += page_cache.o xbzrle.o
>
>   common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
> diff --git a/include/migration/migration.h b/include/migration/migration.h
> index a821c80..a690e18 100644
> --- a/include/migration/migration.h
> +++ b/include/migration/migration.h
> @@ -58,6 +58,17 @@ struct MigrationState
>       int64_t xbzrle_cache_size;
>   };
>
> +
> +typedef struct LocalMigState LocalMigState;
> +
> +struct LocalMigState
> +{
> +    int fd;
> +    int state;
> +    QEMUFile *file;
> +    QemuThread thread;
> +};
> +
>   void process_incoming_migration(QEMUFile *f);
>
>   void qemu_start_incoming_migration(const char *uri, Error **errp);
> @@ -80,6 +91,8 @@ void unix_start_incoming_migration(const char *path, Error **errp);
>
>   void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp);
>
> +void unix_start_local_outgoing_migration(LocalMigState *s, const char *path, Error **errp);
> +
>   void fd_start_incoming_migration(const char *path, Error **errp);
>
>   void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp);
> @@ -88,6 +101,8 @@ void migrate_fd_error(MigrationState *s);
>
>   void migrate_fd_connect(MigrationState *s);
>
> +void local_migration_fd_connect(LocalMigState *s);
> +
>   int migrate_fd_close(MigrationState *s);
>
>   void add_migration_state_change_notifier(Notifier *notify);
> diff --git a/migration-local.c b/migration-local.c
> new file mode 100644
> index 0000000..5bd1ed0
> --- /dev/null
> +++ b/migration-local.c
> @@ -0,0 +1,158 @@
> +/*
> + * QEMU localhost migration
> + *
> + * Copyright IBM, Corp. 2013
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.  See
> + * the COPYING file in the top-level directory.
> + *
> + * Contributions are licensed under the terms of the GNU GPL, version 2
> + * or (at your option) any later version.
> + */
> +
> +#include "qemu-common.h"
> +#include "migration/migration.h"
> +#include "monitor/monitor.h"
> +#include "migration/qemu-file.h"
> +#include "sysemu/sysemu.h"
> +#include "block/block.h"
> +#include "qemu/sockets.h"
> +#include "migration/block.h"
> +#include "qemu/thread.h"
> +#include "qmp-commands.h"
> +#include "exec/memory.h"
> +#include "trace.h"
> +#include "qemu/osdep.h"
> +
> +//#define DEBUG_MIGRATION_LOCAL
> +
> +#ifdef DEBUG_MIGRATION_LOCAL
> +#define DPRINTF(fmt, ...) \
> +    do { printf("migration-local: " fmt, ## __VA_ARGS__); } while (0)
> +#else
> +#define DPRINTF(fmt, ...) \
> +    do { } while (0)
> +#endif
> +
> +
> +/************************************************************************
> + * Outgoing part
> + */
> +
> +static LocalMigState *local_migration_init(void)
> +{
> +    LocalMigState *s = g_malloc0(sizeof(*s));
> +
> +    s->state = MIG_STATE_SETUP;
> +    trace_migrate_set_state(MIG_STATE_SETUP);
> +    s->fd = -1;
> +
> +    return s;
> +}
> +
> +static void local_migration_error(LocalMigState *s)
> +{
> +    assert(s->file == NULL);
> +
> +    s->state = MIG_STATE_ERROR;
> +    trace_migrate_set_state(MIG_STATE_ERROR);
> +}
> +
> +static void local_outgoing_completed(LocalMigState *s)
> +{
> +    s->state = MIG_STATE_COMPLETED;
> +    trace_migrate_set_state(MIG_STATE_COMPLETED);
> +}
> +
> +static void *migration_local_thread(void *opaque)
> +{
> +    LocalMigState *s = opaque;
> +    int ret;
> +
> +    DPRINTF("Beginning savevm\n");
> +
> +    while (s->state == MIG_STATE_ACTIVE) {
> +        qemu_mutex_lock_iothread();
> +        ret = qemu_savevm_local(s->file);
> +        qemu_mutex_unlock_iothread();
> +
> +        /* No need to send device states if ram pages fails to to sent. */
> +        if (ret < 0) {
> +            local_migration_error(s);
> +            break;
> +        }
> +
> +        qemu_save_device_state(s->file);
> +        qemu_fclose(s->file);
> +    }
> +
> +    ret = qemu_file_get_error(s->file);
> +    if (ret < 0) {
> +        local_migration_error(s);
> +    } else {
> +        local_outgoing_completed(s);
> +    }
> +
> +    qemu_mutex_lock_iothread();
> +
> +    if (s->state == MIG_STATE_COMPLETED) {
> +        runstate_set(RUN_STATE_POSTMIGRATE);
> +    }
> +
> +    qemu_mutex_unlock_iothread();
> +
> +    return NULL;
> +}
> +
> +void local_migration_fd_connect(LocalMigState *s)
> +{
> +    s->state = MIG_STATE_ACTIVE;
> +    trace_migrate_set_state(MIG_STATE_ACTIVE);
> +
> +    qemu_thread_create(&s->thread, migration_local_thread, s,
> +                       QEMU_THREAD_JOINABLE);
> +}
> +
> +void qmp_localhost_migrate(const char *uri, Error **errp)
> +{
> +    const char *path;
> +    Error *local_err = NULL;
> +    int is_vm_running;
> +    LocalMigState *s;
> +
> +    if (qemu_savevm_state_blocked(errp)) {
> +        return;
> +    }
> +
> +    s = local_migration_init();
> +    bdrv_flush_all();
> +
> +    is_vm_running = runstate_is_running();
> +
> +    /* Stop the VM first */
> +    if (is_vm_running) {
> +        vm_stop(RUN_STATE_SAVE_VM);
> +    }
> +
> +    /* Start outgoing migration by unix socket. */
> +    if (strstart(uri, "unix:", &path)) {
> +        /* XXX. Creat a new unix_start_outgoing_migration_* is not necessary,
> +         * just for the first step. This will be replaced by vmsplice
> +         * mechanism. */
> +        unix_start_local_outgoing_migration(s, path, &local_err);
> +    } else {
> +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
> +        goto fail;
> +    }
> +
> +    if (local_err) {
> +        s->state = MIG_STATE_ERROR;
> +        error_propagate(errp, local_err);
> +        goto fail;
> +    }
> +
> +fail:
> +    if (!is_vm_running) {
> +        vm_start();
> +    }
> +}
> diff --git a/migration-unix.c b/migration-unix.c
> index 94b7022..ec20c45 100644
> --- a/migration-unix.c
> +++ b/migration-unix.c
> @@ -49,6 +49,19 @@ void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **
>       unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
>   }
>
> +void unix_start_local_outgoing_migration(LocalMigState *s, const char *path, Error **errp)
> +{
> +    s->fd = unix_connect(path, errp);
> +    if (s->fd < 0) {
> +        s->file = NULL;
> +        /* There should be a fd_error_set function */
> +        s->state = MIG_STATE_ERROR;
> +    } else {
> +        s->file = qemu_fopen_socket(s->fd, "wb");
> +        local_migration_fd_connect(s);
> +    }
> +}
> +
>   static void unix_accept_incoming_migration(void *opaque)
>   {
>       struct sockaddr_un addr;
> diff --git a/qapi-schema.json b/qapi-schema.json
> index a80ee40..7431a41 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2336,6 +2336,20 @@
>   { 'command': 'migrate',
>     'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }
>
> +##
> +# @localhost-migrate
> +#
> +# Migrates the current running guest to the localhost VM.
> +#
> +# @uri: the Uniform Resource Identifier of the destination VM
> +#
> +# Returns: nothing on success
> +#
> +# Since: 1.7
> +##
> +{ 'command': 'localhost-migrate',
> +  'data': {'uri': 'str'} }
> +
>   # @xen-save-devices-state:
>   #
>   # Save the state of all devices to file. The RAM and the block devices
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 8cea5e5..aba2327 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -640,6 +640,28 @@ Notes:
>   EQMP
>
>       {
> +        .name      = "localhost-migrate",
> +        .args_type = "uri:s",
> +        .mhandler.cmd_new = qmp_marshal_input_localhost_migrate,
> +    },
> +
> +SQMP
> +localhost-migrate
> +
> +Migrate VM in localhost.
> +
> +Arguments:
> +
> +- "uri": Destination URI (json-string)
> +
> +Example:
> +
> +-> { "execute": "localhost-migrate", "arguments": { "uri": "UNIX-SOCKET" }
> +<- { "return": {} }
> +
> +EQMP
> +
> +    {
>           .name       = "migrate_cancel",
>           .args_type  = "",
>           .mhandler.cmd_new = qmp_marshal_input_migrate_cancel,

Why a separate thread? What's wrong with modifying the existing 
migration_thread() ?

- Michael

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] migration-local: add option to commandline for incoming-local
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 11/12] migration-local: add option to commandline for incoming-local Lei Li
@ 2013-08-02 19:46   ` Michael R. Hines
  2013-08-05  3:21     ` Lei Li
  0 siblings, 1 reply; 28+ messages in thread
From: Michael R. Hines @ 2013-08-02 19:46 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   qemu-options.hx |    9 +++++++++
>   vl.c            |   14 ++++++++++++++
>   2 files changed, 23 insertions(+), 0 deletions(-)
>
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 8355f9b..a975e83 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -2912,6 +2912,15 @@ STEXI
>   Prepare for incoming migration, listen on @var{port}.
>   ETEXI
>
> +DEF("incoming-local", HAS_ARG, QEMU_OPTION_incoming_local, \
> +    "-incoming-local p prepare for localhost incoming migration, listen on domain unix socket p\n",
> +    QEMU_ARCH_ALL)
> +STEXI
> +@item -incoming-local @var{port}
> +@findex -incoming-local
> +Prepare for localhost incoming migration, listen on @var{port}
> +ETEXI
> +
>   DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
>       "-nodefaults     don't create default devices\n", QEMU_ARCH_ALL)
>   STEXI
> diff --git a/vl.c b/vl.c
> index 767e020..b820db5 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2854,6 +2854,7 @@ int main(int argc, char **argv, char **envp)
>       const char *vga_model = "none";
>       const char *pid_file = NULL;
>       const char *incoming = NULL;
> +    const char *incoming_local = NULL;
>   #ifdef CONFIG_VNC
>       int show_vnc_port = 0;
>   #endif
> @@ -3691,6 +3692,10 @@ int main(int argc, char **argv, char **envp)
>                   incoming = optarg;
>                   runstate_set(RUN_STATE_INMIGRATE);
>                   break;
> +            case QEMU_OPTION_incoming_local:
> +                incoming_local = optarg;
> +                runstate_set(RUN_STATE_INMIGRATE);
> +                break;
>               case QEMU_OPTION_nodefaults:
>                   default_serial = 0;
>                   default_parallel = 0;
> @@ -4377,6 +4382,15 @@ int main(int argc, char **argv, char **envp)
>               error_free(local_err);
>               exit(1);
>           }
> +    } else if (incoming_local) {
> +        Error *local_err = NULL;
> +        qemu_start_local_incoming_migration(incoming_local, &local_err);
> +        if (local_err) {
> +            fprintf(stderr, "-incoming_local %s: %s\n", incoming_local,
> +                    error_get_pretty(local_err));
> +            error_free(local_err);
> +            exit(1);
> +        }
>       } else if (autostart) {
>           vm_start();
>       }

Why can't we do: -incoming "local:" instead of adding a new flag?

Would be much more compatible with libvirt tools if you just add a new 
URI prefix.....

- Michael

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 12/12] hmp: add hmp_localhost_migration interface
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 12/12] hmp: add hmp_localhost_migration interface Lei Li
@ 2013-08-02 19:47   ` Michael R. Hines
  2013-08-05  3:22     ` Lei Li
  0 siblings, 1 reply; 28+ messages in thread
From: Michael R. Hines @ 2013-08-02 19:47 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   hmp-commands.hx |   17 +++++++++++++++++
>   hmp.c           |   13 +++++++++++++
>   hmp.h           |    1 +
>   3 files changed, 31 insertions(+), 0 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 915b0d1..ed21970 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -989,6 +989,23 @@ STEXI
>   Set the spice/vnc connection info for the migration target.  The spice/vnc
>   server will ask the spice/vnc client to automatically reconnect using the
>   new parameters (if specified) once the vm migration finished successfully.
> +
> +ETEXI
> +
> +    {
> +        .name       = "localhost_migrate",
> +        .args_type  = "uri:s",
> +        .params     = "uri",
> +        .help       = "migrate to domain socket URI on localhost",
> +        .mhandler.cmd = hmp_localhost_migrate,
> +    },
> +
> +
> +STEXI
> +@item localhost_migrate @var{uri}
> +@findex localhost_migrate
> +Migrate to @var{uri}.
> +
>   ETEXI
>
>       {
> diff --git a/hmp.c b/hmp.c
> index 494a9aa..a7e779f 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1191,6 +1191,19 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
>       }
>   }
>
> +void hmp_localhost_migrate(Monitor *mon, const QDict *qdict)
> +{
> +    const char *uri = qdict_get_str(qdict, "uri");
> +    Error *errp = NULL;
> +
> +    qmp_localhost_migrate(uri, &errp);
> +    if (errp) {
> +        monitor_printf(mon, "local_migrate: %s\n", error_get_pretty(errp));
> +        error_free(errp);
> +        return;
> +    }
> +}
> +
>   void hmp_device_del(Monitor *mon, const QDict *qdict)
>   {
>       const char *id = qdict_get_str(qdict, "id");
> diff --git a/hmp.h b/hmp.h
> index 56d2e92..9124c0e 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -60,6 +60,7 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
>   void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
>   void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
>   void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
> +void hmp_localhost_migrate(Monitor *mon, const QDict *qdict);
>   void hmp_set_password(Monitor *mon, const QDict *qdict);
>   void hmp_expire_password(Monitor *mon, const QDict *qdict);
>   void hmp_eject(Monitor *mon, const QDict *qdict);

This could go away if you just create a new URI prefix instead of a new 
command-line switch.

- Michael

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] savevm: introduce qemu_savevm_local()
  2013-07-25 20:18 ` [Qemu-devel] [PATCH 07/12] savevm: introduce qemu_savevm_local() Lei Li
@ 2013-08-02 19:48   ` Michael R. Hines
  2013-08-05  3:02     ` Lei Li
  0 siblings, 1 reply; 28+ messages in thread
From: Michael R. Hines @ 2013-08-02 19:48 UTC (permalink / raw)
  To: Lei Li; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 07/25/2013 04:18 PM, Lei Li wrote:
> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
> ---
>   include/sysemu/sysemu.h |    1 +
>   savevm.c                |   55 +++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 56 insertions(+), 0 deletions(-)
>
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 5b90027..9abe4c9 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -80,6 +80,7 @@ int qemu_savevm_state_iterate(QEMUFile *f);
>   void qemu_savevm_state_complete(QEMUFile *f);
>   void qemu_savevm_state_cancel(void);
>   uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
> +int qemu_savevm_local(QEMUFile *f);
>   int qemu_save_device_state(QEMUFile *f);
>   int qemu_loadvm_state(QEMUFile *f);
>
> diff --git a/savevm.c b/savevm.c
> index e18ca22..c183369 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -2007,6 +2007,61 @@ static int qemu_savevm_state(QEMUFile *f)
>   }
>
>   /**
> + * Save all of the ram pages to stream QEMUFile
> + *
> + * Return: negtive for an error
> + */
> +int qemu_savevm_local(QEMUFile *f)
> +{
> +    SaveStateEntry *se;
> +    int ret;
> +
> +    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
> +        if (!se->ops) {
> +            continue;
> +        }
> +    }
> +
> +    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
> +    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
> +
> +    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
> +        int len;
> +
> +        if (!se->ops || !se->ops->save_local_setup) {
> +            continue;
> +        }
> +        if (se->ops && se->ops->is_block_active) {
> +            continue;
> +        }
> +
> +        /* Section type */
> +        qemu_put_byte(f, QEMU_VM_SECTION_START);
> +        qemu_put_be32(f, se->section_id);
> +
> +        /* ID string */
> +        len = strlen(se->idstr);
> +        qemu_put_byte(f, len);
> +        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
> +
> +        qemu_put_be32(f, se->instance_id);
> +
> +        qemu_put_be32(f, se->version_id);
> +
> +        ret = se->ops->save_local_setup(f, se->opaque);
> +        if (ret < 0) {
> +            qemu_file_set_error(f, ret);
> +            break;
> +        }
> +    }
> +
> +    qemu_put_byte(f, QEMU_VM_EOF);
> +    qemu_fflush(f);
> +
> +    return qemu_file_get_error(f);
> +}
> +
> +/**
>    * Save all of the device states to stream QEMUFile
>    *
>    * Return negtive if there has been an error

You don't have enough comments in your commit messages - please add more.

Why do you need a new savevm function?

- Michael

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/12] arch_init: introduce ram_page_save()
  2013-08-02 19:40   ` Michael R. Hines
@ 2013-08-05  2:49     ` Lei Li
  0 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-08-05  2:49 UTC (permalink / raw)
  To: Michael R. Hines
  Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 08/03/2013 03:40 AM, Michael R. Hines wrote:
> On 07/25/2013 04:18 PM, Lei Li wrote:
>> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
>> ---
>>   arch_init.c |   58 
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 files changed, 58 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch_init.c b/arch_init.c
>> index a8b91ee..a418071 100644
>> --- a/arch_init.c
>> +++ b/arch_init.c
>> @@ -699,6 +699,64 @@ static uint64_t ram_save_pending(QEMUFile *f, 
>> void *opaque, uint64_t max_size)
>>       return remaining_size;
>>   }
>>
>> +/* This is the last block from where we have sent data for local 
>> migration */
>> +static RAMBlock *last_block_local;
>> +static ram_addr_t last_offset_local;
>> +
>> +static int ram_page_save(QEMUFile *f)
>> +{
>> +    RAMBlock *block = last_block_local;
>> +    ram_addr_t offset = last_offset_local;
>> +    MemoryRegion *mr = block->mr;
>> +    int bytes_sent = 0;
>> +
>> +    if (!block) {
>> +        block = QTAILQ_FIRST(&ram_list.blocks);
>> +    }
>> +
>> +    do {
>> +        mr = block->mr;
>> +        uint8_t *p;
>> +        int cont = (block == last_block_local) ? 
>> RAM_SAVE_FLAG_CONTINUE : 0;
>> +
>> +        p = memory_region_get_ram_ptr(mr) + offset;
>> +
>> +        if (is_zero_page(p)) {
>> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS);
>> +            if (!cont) {
>> +                qemu_put_byte(f, strlen(block->idstr));
>> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
>> +                                strlen(block->idstr));
>> +            }
>> +            qemu_put_byte(f, *p);
>> +            bytes_sent = 1;
>> +        } else {
>> +            qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_PAGE);
>> +            if (!cont) {
>> +                qemu_put_byte(f, strlen(block->idstr));
>> +                qemu_put_buffer(f, (uint8_t *)block->idstr,
>> +                                strlen(block->idstr));
>> +            }
>> +            qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
>> +            bytes_sent = TARGET_PAGE_SIZE;
>> +        }
>> +
>> +        offset += TARGET_PAGE_SIZE;
>> +        if (offset >= block->length) {
>> +            offset = 0;
>> +            block = QTAILQ_NEXT(block, next);
>> +            if (!block) {
>> +                block = QTAILQ_FIRST(&ram_list.blocks);
>> +            }
>> +        }
>> +    } while (block != last_block_local || offset != last_offset_local);
>> +
>> +    last_block_local = block;
>> +    last_offset_local = offset;
>> +
>> +    return bytes_sent;
>> +}
>> +
>>   static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
>>   {
>>       int ret, rc = 0;
>
> Seems like there's a lot of duplicate code.
>
> We have new hooks to override the way memory is saved in arch_init.c
>
> See the QEMUFileOps......... save_page() / before_ram_iterate() / 
> after_ram_iterate()
>
> You might need to introduce a new "load_page()" pointer in QEMUFileOps.
>
> Then all this code can be private to migration-local.c

Hi Michael,

This implementation was based on the tree that rdma migration you added have
not been merged...

Yes, Paolo also suggested that reuses the rdma hooks and I am trying to figure
it out. Your comments really helps, thanks for your suggestions!
  

>
> - Michael
>
>
>


-- 
Lei

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] savevm: introduce qemu_savevm_local()
  2013-08-02 19:48   ` Michael R. Hines
@ 2013-08-05  3:02     ` Lei Li
  0 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-08-05  3:02 UTC (permalink / raw)
  To: Michael R. Hines
  Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 08/03/2013 03:48 AM, Michael R. Hines wrote:
> On 07/25/2013 04:18 PM, Lei Li wrote:
>> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
>> ---
>>   include/sysemu/sysemu.h |    1 +
>>   savevm.c                |   55 
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 56 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
>> index 5b90027..9abe4c9 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -80,6 +80,7 @@ int qemu_savevm_state_iterate(QEMUFile *f);
>>   void qemu_savevm_state_complete(QEMUFile *f);
>>   void qemu_savevm_state_cancel(void);
>>   uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
>> +int qemu_savevm_local(QEMUFile *f);
>>   int qemu_save_device_state(QEMUFile *f);
>>   int qemu_loadvm_state(QEMUFile *f);
>>
>> diff --git a/savevm.c b/savevm.c
>> index e18ca22..c183369 100644
>> --- a/savevm.c
>> +++ b/savevm.c
>> @@ -2007,6 +2007,61 @@ static int qemu_savevm_state(QEMUFile *f)
>>   }
>>
>>   /**
>> + * Save all of the ram pages to stream QEMUFile
>> + *
>> + * Return: negtive for an error
>> + */
>> +int qemu_savevm_local(QEMUFile *f)
>> +{
>> +    SaveStateEntry *se;
>> +    int ret;
>> +
>> +    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
>> +        if (!se->ops) {
>> +            continue;
>> +        }
>> +    }
>> +
>> +    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
>> +    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
>> +
>> +    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
>> +        int len;
>> +
>> +        if (!se->ops || !se->ops->save_local_setup) {
>> +            continue;
>> +        }
>> +        if (se->ops && se->ops->is_block_active) {
>> +            continue;
>> +        }
>> +
>> +        /* Section type */
>> +        qemu_put_byte(f, QEMU_VM_SECTION_START);
>> +        qemu_put_be32(f, se->section_id);
>> +
>> +        /* ID string */
>> +        len = strlen(se->idstr);
>> +        qemu_put_byte(f, len);
>> +        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
>> +
>> +        qemu_put_be32(f, se->instance_id);
>> +
>> +        qemu_put_be32(f, se->version_id);
>> +
>> +        ret = se->ops->save_local_setup(f, se->opaque);
>> +        if (ret < 0) {
>> +            qemu_file_set_error(f, ret);
>> +            break;
>> +        }
>> +    }
>> +
>> +    qemu_put_byte(f, QEMU_VM_EOF);
>> +    qemu_fflush(f);
>> +
>> +    return qemu_file_get_error(f);
>> +}
>> +
>> +/**
>>    * Save all of the device states to stream QEMUFile
>>    *
>>    * Return negtive if there has been an error
>
> You don't have enough comments in your commit messages - please add more.

Sorry for the missing of commit messages..

>
> Why do you need a new savevm function?

qemu_savevm_local() is introduced to savevm layer that begin
and do the local migration by calling ops->save_local_setup which
is added to savevm_ram_handlers.

>
> - Michael


-- 
Lei

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 09/12] migration-local: implementation of outgoing part
  2013-08-02 19:45   ` Michael R. Hines
@ 2013-08-05  3:18     ` Lei Li
  0 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-08-05  3:18 UTC (permalink / raw)
  To: Michael R. Hines
  Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 08/03/2013 03:45 AM, Michael R. Hines wrote:
> On 07/25/2013 04:18 PM, Lei Li wrote:
>> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
>> ---
>>   Makefile.objs                 |    1 +
>>   include/migration/migration.h |   15 ++++
>>   migration-local.c             |  158 
>> +++++++++++++++++++++++++++++++++++++++++
>>   migration-unix.c              |   13 ++++
>>   qapi-schema.json              |   14 ++++
>>   qmp-commands.hx               |   22 ++++++
>>   6 files changed, 223 insertions(+), 0 deletions(-)
>>   create mode 100644 migration-local.c
>>
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 5b288ba..2a3d9a5 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -53,6 +53,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
>>   common-obj-y += migration.o migration-tcp.o
>>   common-obj-y += qemu-char.o #aio.o
>>   common-obj-y += block-migration.o
>> +common-obj-y += migration-local.o
>>   common-obj-y += page_cache.o xbzrle.o
>>
>>   common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o 
>> migration-fd.o
>> diff --git a/include/migration/migration.h 
>> b/include/migration/migration.h
>> index a821c80..a690e18 100644
>> --- a/include/migration/migration.h
>> +++ b/include/migration/migration.h
>> @@ -58,6 +58,17 @@ struct MigrationState
>>       int64_t xbzrle_cache_size;
>>   };
>>
>> +
>> +typedef struct LocalMigState LocalMigState;
>> +
>> +struct LocalMigState
>> +{
>> +    int fd;
>> +    int state;
>> +    QEMUFile *file;
>> +    QemuThread thread;
>> +};
>> +
>>   void process_incoming_migration(QEMUFile *f);
>>
>>   void qemu_start_incoming_migration(const char *uri, Error **errp);
>> @@ -80,6 +91,8 @@ void unix_start_incoming_migration(const char 
>> *path, Error **errp);
>>
>>   void unix_start_outgoing_migration(MigrationState *s, const char 
>> *path, Error **errp);
>>
>> +void unix_start_local_outgoing_migration(LocalMigState *s, const 
>> char *path, Error **errp);
>> +
>>   void fd_start_incoming_migration(const char *path, Error **errp);
>>
>>   void fd_start_outgoing_migration(MigrationState *s, const char 
>> *fdname, Error **errp);
>> @@ -88,6 +101,8 @@ void migrate_fd_error(MigrationState *s);
>>
>>   void migrate_fd_connect(MigrationState *s);
>>
>> +void local_migration_fd_connect(LocalMigState *s);
>> +
>>   int migrate_fd_close(MigrationState *s);
>>
>>   void add_migration_state_change_notifier(Notifier *notify);
>> diff --git a/migration-local.c b/migration-local.c
>> new file mode 100644
>> index 0000000..5bd1ed0
>> --- /dev/null
>> +++ b/migration-local.c
>> @@ -0,0 +1,158 @@
>> +/*
>> + * QEMU localhost migration
>> + *
>> + * Copyright IBM, Corp. 2013
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2.  
>> See
>> + * the COPYING file in the top-level directory.
>> + *
>> + * Contributions are licensed under the terms of the GNU GPL, version 2
>> + * or (at your option) any later version.
>> + */
>> +
>> +#include "qemu-common.h"
>> +#include "migration/migration.h"
>> +#include "monitor/monitor.h"
>> +#include "migration/qemu-file.h"
>> +#include "sysemu/sysemu.h"
>> +#include "block/block.h"
>> +#include "qemu/sockets.h"
>> +#include "migration/block.h"
>> +#include "qemu/thread.h"
>> +#include "qmp-commands.h"
>> +#include "exec/memory.h"
>> +#include "trace.h"
>> +#include "qemu/osdep.h"
>> +
>> +//#define DEBUG_MIGRATION_LOCAL
>> +
>> +#ifdef DEBUG_MIGRATION_LOCAL
>> +#define DPRINTF(fmt, ...) \
>> +    do { printf("migration-local: " fmt, ## __VA_ARGS__); } while (0)
>> +#else
>> +#define DPRINTF(fmt, ...) \
>> +    do { } while (0)
>> +#endif
>> +
>> +
>> +/************************************************************************ 
>>
>> + * Outgoing part
>> + */
>> +
>> +static LocalMigState *local_migration_init(void)
>> +{
>> +    LocalMigState *s = g_malloc0(sizeof(*s));
>> +
>> +    s->state = MIG_STATE_SETUP;
>> +    trace_migrate_set_state(MIG_STATE_SETUP);
>> +    s->fd = -1;
>> +
>> +    return s;
>> +}
>> +
>> +static void local_migration_error(LocalMigState *s)
>> +{
>> +    assert(s->file == NULL);
>> +
>> +    s->state = MIG_STATE_ERROR;
>> +    trace_migrate_set_state(MIG_STATE_ERROR);
>> +}
>> +
>> +static void local_outgoing_completed(LocalMigState *s)
>> +{
>> +    s->state = MIG_STATE_COMPLETED;
>> +    trace_migrate_set_state(MIG_STATE_COMPLETED);
>> +}
>> +
>> +static void *migration_local_thread(void *opaque)
>> +{
>> +    LocalMigState *s = opaque;
>> +    int ret;
>> +
>> +    DPRINTF("Beginning savevm\n");
>> +
>> +    while (s->state == MIG_STATE_ACTIVE) {
>> +        qemu_mutex_lock_iothread();
>> +        ret = qemu_savevm_local(s->file);
>> +        qemu_mutex_unlock_iothread();
>> +
>> +        /* No need to send device states if ram pages fails to to 
>> sent. */
>> +        if (ret < 0) {
>> +            local_migration_error(s);
>> +            break;
>> +        }
>> +
>> +        qemu_save_device_state(s->file);
>> +        qemu_fclose(s->file);
>> +    }
>> +
>> +    ret = qemu_file_get_error(s->file);
>> +    if (ret < 0) {
>> +        local_migration_error(s);
>> +    } else {
>> +        local_outgoing_completed(s);
>> +    }
>> +
>> +    qemu_mutex_lock_iothread();
>> +
>> +    if (s->state == MIG_STATE_COMPLETED) {
>> +        runstate_set(RUN_STATE_POSTMIGRATE);
>> +    }
>> +
>> +    qemu_mutex_unlock_iothread();
>> +
>> +    return NULL;
>> +}
>> +
>> +void local_migration_fd_connect(LocalMigState *s)
>> +{
>> +    s->state = MIG_STATE_ACTIVE;
>> +    trace_migrate_set_state(MIG_STATE_ACTIVE);
>> +
>> +    qemu_thread_create(&s->thread, migration_local_thread, s,
>> +                       QEMU_THREAD_JOINABLE);
>> +}
>> +
>> +void qmp_localhost_migrate(const char *uri, Error **errp)
>> +{
>> +    const char *path;
>> +    Error *local_err = NULL;
>> +    int is_vm_running;
>> +    LocalMigState *s;
>> +
>> +    if (qemu_savevm_state_blocked(errp)) {
>> +        return;
>> +    }
>> +
>> +    s = local_migration_init();
>> +    bdrv_flush_all();
>> +
>> +    is_vm_running = runstate_is_running();
>> +
>> +    /* Stop the VM first */
>> +    if (is_vm_running) {
>> +        vm_stop(RUN_STATE_SAVE_VM);
>> +    }
>> +
>> +    /* Start outgoing migration by unix socket. */
>> +    if (strstart(uri, "unix:", &path)) {
>> +        /* XXX. Creat a new unix_start_outgoing_migration_* is not 
>> necessary,
>> +         * just for the first step. This will be replaced by vmsplice
>> +         * mechanism. */
>> +        unix_start_local_outgoing_migration(s, path, &local_err);
>> +    } else {
>> +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a 
>> valid migration protocol");
>> +        goto fail;
>> +    }
>> +
>> +    if (local_err) {
>> +        s->state = MIG_STATE_ERROR;
>> +        error_propagate(errp, local_err);
>> +        goto fail;
>> +    }
>> +
>> +fail:
>> +    if (!is_vm_running) {
>> +        vm_start();
>> +    }
>> +}
>> diff --git a/migration-unix.c b/migration-unix.c
>> index 94b7022..ec20c45 100644
>> --- a/migration-unix.c
>> +++ b/migration-unix.c
>> @@ -49,6 +49,19 @@ void unix_start_outgoing_migration(MigrationState 
>> *s, const char *path, Error **
>>       unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
>>   }
>>
>> +void unix_start_local_outgoing_migration(LocalMigState *s, const 
>> char *path, Error **errp)
>> +{
>> +    s->fd = unix_connect(path, errp);
>> +    if (s->fd < 0) {
>> +        s->file = NULL;
>> +        /* There should be a fd_error_set function */
>> +        s->state = MIG_STATE_ERROR;
>> +    } else {
>> +        s->file = qemu_fopen_socket(s->fd, "wb");
>> +        local_migration_fd_connect(s);
>> +    }
>> +}
>> +
>>   static void unix_accept_incoming_migration(void *opaque)
>>   {
>>       struct sockaddr_un addr;
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index a80ee40..7431a41 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -2336,6 +2336,20 @@
>>   { 'command': 'migrate',
>>     'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 
>> 'bool' } }
>>
>> +##
>> +# @localhost-migrate
>> +#
>> +# Migrates the current running guest to the localhost VM.
>> +#
>> +# @uri: the Uniform Resource Identifier of the destination VM
>> +#
>> +# Returns: nothing on success
>> +#
>> +# Since: 1.7
>> +##
>> +{ 'command': 'localhost-migrate',
>> +  'data': {'uri': 'str'} }
>> +
>>   # @xen-save-devices-state:
>>   #
>>   # Save the state of all devices to file. The RAM and the block devices
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index 8cea5e5..aba2327 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -640,6 +640,28 @@ Notes:
>>   EQMP
>>
>>       {
>> +        .name      = "localhost-migrate",
>> +        .args_type = "uri:s",
>> +        .mhandler.cmd_new = qmp_marshal_input_localhost_migrate,
>> +    },
>> +
>> +SQMP
>> +localhost-migrate
>> +
>> +Migrate VM in localhost.
>> +
>> +Arguments:
>> +
>> +- "uri": Destination URI (json-string)
>> +
>> +Example:
>> +
>> +-> { "execute": "localhost-migrate", "arguments": { "uri": 
>> "UNIX-SOCKET" }
>> +<- { "return": {} }
>> +
>> +EQMP
>> +
>> +    {
>>           .name       = "migrate_cancel",
>>           .args_type  = "",
>>           .mhandler.cmd_new = qmp_marshal_input_migrate_cancel,
>
> Why a separate thread? What's wrong with modifying the existing 
> migration_thread() ?

Well, as mentioned in the cover letter, it was implemented
separately to the current migration code just for a easier start..
I am looking for suggestions on the proper way to integrate it.

Yes, modify the existing migration_thread() is an option.

>
> - Michael
>
>


-- 
Lei

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] migration-local: add option to commandline for incoming-local
  2013-08-02 19:46   ` Michael R. Hines
@ 2013-08-05  3:21     ` Lei Li
  0 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-08-05  3:21 UTC (permalink / raw)
  To: Michael R. Hines
  Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 08/03/2013 03:46 AM, Michael R. Hines wrote:
> On 07/25/2013 04:18 PM, Lei Li wrote:
>> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
>> ---
>>   qemu-options.hx |    9 +++++++++
>>   vl.c            |   14 ++++++++++++++
>>   2 files changed, 23 insertions(+), 0 deletions(-)
>>
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index 8355f9b..a975e83 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -2912,6 +2912,15 @@ STEXI
>>   Prepare for incoming migration, listen on @var{port}.
>>   ETEXI
>>
>> +DEF("incoming-local", HAS_ARG, QEMU_OPTION_incoming_local, \
>> +    "-incoming-local p prepare for localhost incoming migration, 
>> listen on domain unix socket p\n",
>> +    QEMU_ARCH_ALL)
>> +STEXI
>> +@item -incoming-local @var{port}
>> +@findex -incoming-local
>> +Prepare for localhost incoming migration, listen on @var{port}
>> +ETEXI
>> +
>>   DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
>>       "-nodefaults     don't create default devices\n", QEMU_ARCH_ALL)
>>   STEXI
>> diff --git a/vl.c b/vl.c
>> index 767e020..b820db5 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -2854,6 +2854,7 @@ int main(int argc, char **argv, char **envp)
>>       const char *vga_model = "none";
>>       const char *pid_file = NULL;
>>       const char *incoming = NULL;
>> +    const char *incoming_local = NULL;
>>   #ifdef CONFIG_VNC
>>       int show_vnc_port = 0;
>>   #endif
>> @@ -3691,6 +3692,10 @@ int main(int argc, char **argv, char **envp)
>>                   incoming = optarg;
>>                   runstate_set(RUN_STATE_INMIGRATE);
>>                   break;
>> +            case QEMU_OPTION_incoming_local:
>> +                incoming_local = optarg;
>> +                runstate_set(RUN_STATE_INMIGRATE);
>> +                break;
>>               case QEMU_OPTION_nodefaults:
>>                   default_serial = 0;
>>                   default_parallel = 0;
>> @@ -4377,6 +4382,15 @@ int main(int argc, char **argv, char **envp)
>>               error_free(local_err);
>>               exit(1);
>>           }
>> +    } else if (incoming_local) {
>> +        Error *local_err = NULL;
>> +        qemu_start_local_incoming_migration(incoming_local, 
>> &local_err);
>> +        if (local_err) {
>> +            fprintf(stderr, "-incoming_local %s: %s\n", incoming_local,
>> +                    error_get_pretty(local_err));
>> +            error_free(local_err);
>> +            exit(1);
>> +        }
>>       } else if (autostart) {
>>           vm_start();
>>       }
>
> Why can't we do: -incoming "local:" instead of adding a new flag?
>
> Would be much more compatible with libvirt tools if you just add a new 
> URI prefix.....

Good suggestion, thanks!

>
> - Michael
>
>


-- 
Lei

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 12/12] hmp: add hmp_localhost_migration interface
  2013-08-02 19:47   ` Michael R. Hines
@ 2013-08-05  3:22     ` Lei Li
  0 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-08-05  3:22 UTC (permalink / raw)
  To: Michael R. Hines
  Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 08/03/2013 03:47 AM, Michael R. Hines wrote:
> On 07/25/2013 04:18 PM, Lei Li wrote:
>> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
>> ---
>>   hmp-commands.hx |   17 +++++++++++++++++
>>   hmp.c           |   13 +++++++++++++
>>   hmp.h           |    1 +
>>   3 files changed, 31 insertions(+), 0 deletions(-)
>>
>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>> index 915b0d1..ed21970 100644
>> --- a/hmp-commands.hx
>> +++ b/hmp-commands.hx
>> @@ -989,6 +989,23 @@ STEXI
>>   Set the spice/vnc connection info for the migration target. The 
>> spice/vnc
>>   server will ask the spice/vnc client to automatically reconnect 
>> using the
>>   new parameters (if specified) once the vm migration finished 
>> successfully.
>> +
>> +ETEXI
>> +
>> +    {
>> +        .name       = "localhost_migrate",
>> +        .args_type  = "uri:s",
>> +        .params     = "uri",
>> +        .help       = "migrate to domain socket URI on localhost",
>> +        .mhandler.cmd = hmp_localhost_migrate,
>> +    },
>> +
>> +
>> +STEXI
>> +@item localhost_migrate @var{uri}
>> +@findex localhost_migrate
>> +Migrate to @var{uri}.
>> +
>>   ETEXI
>>
>>       {
>> diff --git a/hmp.c b/hmp.c
>> index 494a9aa..a7e779f 100644
>> --- a/hmp.c
>> +++ b/hmp.c
>> @@ -1191,6 +1191,19 @@ void hmp_migrate(Monitor *mon, const QDict 
>> *qdict)
>>       }
>>   }
>>
>> +void hmp_localhost_migrate(Monitor *mon, const QDict *qdict)
>> +{
>> +    const char *uri = qdict_get_str(qdict, "uri");
>> +    Error *errp = NULL;
>> +
>> +    qmp_localhost_migrate(uri, &errp);
>> +    if (errp) {
>> +        monitor_printf(mon, "local_migrate: %s\n", 
>> error_get_pretty(errp));
>> +        error_free(errp);
>> +        return;
>> +    }
>> +}
>> +
>>   void hmp_device_del(Monitor *mon, const QDict *qdict)
>>   {
>>       const char *id = qdict_get_str(qdict, "id");
>> diff --git a/hmp.h b/hmp.h
>> index 56d2e92..9124c0e 100644
>> --- a/hmp.h
>> +++ b/hmp.h
>> @@ -60,6 +60,7 @@ void hmp_migrate_set_downtime(Monitor *mon, const 
>> QDict *qdict);
>>   void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
>>   void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
>>   void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
>> +void hmp_localhost_migrate(Monitor *mon, const QDict *qdict);
>>   void hmp_set_password(Monitor *mon, const QDict *qdict);
>>   void hmp_expire_password(Monitor *mon, const QDict *qdict);
>>   void hmp_eject(Monitor *mon, const QDict *qdict);
>
> This could go away if you just create a new URI prefix instead of a 
> new command-line switch.

Yes, you are right.
I think a new URI prefix is a good idea.

>
> - Michael


-- 
Lei

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 05/12] arch_init: introduce ram_save_local()
  2013-08-02 19:42   ` Michael R. Hines
@ 2013-08-05  3:27     ` Lei Li
  0 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-08-05  3:27 UTC (permalink / raw)
  To: Michael R. Hines
  Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, pbonzini, rcj

On 08/03/2013 03:42 AM, Michael R. Hines wrote:
> On 07/25/2013 04:18 PM, Lei Li wrote:
>> Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
>> ---
>>   arch_init.c |   32 ++++++++++++++++++++++++++++++++
>>   1 files changed, 32 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch_init.c b/arch_init.c
>> index a418071..7eeb52f 100644
>> --- a/arch_init.c
>> +++ b/arch_init.c
>> @@ -757,6 +757,38 @@ static int ram_page_save(QEMUFile *f)
>>       return bytes_sent;
>>   }
>>
>> +static int ram_save_local(QEMUFile *f, void *opaque)
>> +{
>> +    uint64_t bytes_sent = 0;
>> +    uint64_t total_ram_bytes = ram_bytes_total();
>> +
>> +    qemu_mutex_lock_ramlist();
>> +
>> +    while (total_ram_bytes) {
>> +       void *ram;
>> +       MemoryRegion *mr;
>> +
>> +       bytes_sent = ram_page_save(f);
>> +       /* No more ram pages. */
>> +       if (bytes_sent == 0) {
>> +           return bytes_sent;
>> +       }
>> +
>> +       mr = last_block_local->mr;
>> +       ram = memory_region_get_ram_ptr(mr) + last_offset_local;
>> +
>> +       /* DONTNEED the ram page that has already copied. */
>> +       qemu_madvise(ram, bytes_sent, QEMU_MADV_DONTNEED);
>> +       total_ram_bytes -= bytes_sent;
>> +    }
>> +
>> +    qemu_mutex_unlock_ramlist();
>> +
>> +    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
>> +
>> +    return bytes_sent;
>> +}
>> +
>>   static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
>>   {
>>       int ret, rc = 0;
>
> You need to create a new private structure "QEMUFileLocal".
>
> Then override f->save_page and point this to your own function.
>
> See migration-rdma.c for an example.

Yes, I am looking at it. :)

>
> - Michael


-- 
Lei

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration
  2013-07-26  9:41 ` [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Paolo Bonzini
@ 2013-08-05  8:56   ` Lei Li
  0 siblings, 0 replies; 28+ messages in thread
From: Lei Li @ 2013-08-05  8:56 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: aarcange, aliguori, quintela, qemu-devel, lagarcia, rcj

On 07/26/2013 05:41 PM, Paolo Bonzini wrote:
> Il 25/07/2013 22:18, Lei Li ha scritto:
>> Hi,
>>
>> This patch series tries to add localhost migration support to
>> Qemu.
>>
>> When doing localhost migration, the host memory will balloon
>> up during the period, might consume double memories for some time.
>> So we want to add a new live migration mechanism localhost
>> migration.
>>
>> Following I copied from last version that Anthony added for the
>> benefit of the other reviewers:
>>
>> The goal here is to allow "live upgrade" of a running QEMU instance.
>> The work flow would look like this:
>>
>> 1) Guests are running QEMU release 1.6.1
>> 2) Admin installs QEMU release 1.6.2 via RPM or deb
>> 3) Admin does localhost migration with page flipping to use new version
>>     of QEMU.
>>
>> Page flipping is used in order to avoid requiring that there is enough
>> free memory to fit an additional copy of the largest guest which is the
>> requirement today with localhost migration.
>>
>> You can also read from the link below:
>> http://lists.gnu.org/archive/html/qemu-devel/2013-06/msg02577.html
>>
>> The plan is:
>>
>> 1) Add new command to do localhost migration.
>>
>>     The qmp interface introduced like:
>>
>>     { 'command': 'localhost-migrate', 'data': {'uri': 'str'} }
>>
>> 2) Use different mechanism than current live migration.
>>
>>     The very basic work flow like:
>>
>>         qemu on the source (the source and destination are both on localhost)
>>                |
>>                V
>>             Stop VM
>>                |
>>                V
>>            Create threads
>>                |
>>                V
>>         Page flipping through vmspice
>>                |
>>                V
>>         MADV_DONTNEED the ram pages which are already flipped
>>                |
>>                V
>>         Migration completes
>>
>>     As stopping VM first, we expect/resume the page flipping through vmspice
>>     is fast enough to meet *live migration (low downtime).
>>
>> Notes:
>> Currently the work flow is not exactly the same as description
>> above. For the first step, the work flow we implemented is:
>> stop VM and copy ram pages via unix domain socket, MADV_DONTNEED
>> ram pages that already copied. After that, will replace to vmsplice
>> mechanism instead of copying pages.
>>
>> Now it's still a draft version, and as it is implemented separately
>> to the current migration code for a easy start, the next step will
>> be trying to integrate it into the current migration implementation
>> closely. To make sure we are on the right direction that should be
>> headed, please let me know your suggestions on this.
>>
>> For the interface, as Anthony has suggested using a flag or a
>> capability, which one would you prefer or any ideas?
> Using a capability on the source makes sense; I don't think anything
> special is needed on the destination.  The destination just sees a
> special packet telling it that a pipe is available via SCM_RIGHTS; then
> it fetches the file descriptor and uses it for the new protocol.
>
> It looks like this could reuse a lot of the RAM copying hooks that we
> introduced for RDMA.  You shouldn't need to change anything in savevm.c
> or arch_init.c

Hi Paolo,

Thanks for your suggestions!

And sorry for the late reply, I am looking into RDMA implementation and
trying to figure out the way to integrate with its approach as you suggested.

For the interface on the source, I am OK with using a capability.
For the destination, currently we are copying ram pages via unix
domain socket as first step, will replace to pipe later. How about
add a new URI prefix as Michael R.Hines suggested?



> Paolo
>
>> Your comments are very welcome!
>>
>> TODO:
>> - Integrate to the current implement of migration closely?
>> - Introduce a mechanism to exchange a PIPE via SCM_RIGHTS.
>> - benchmark/evaluation.
>>
>> Lei Li (12):
>>    migration: export MIG_STATE_xxx flags
>>    savevm: export qemu_save_device_state()
>>    rename is_active to is_block_active
>>    arch_init: introduce ram_page_save()
>>    arch_init: introduce ram_save_local()
>>    arch_init: add save_local_setup to savevm_ram_handlers
>>    savevm: introduce qemu_savevm_local()
>>    savevm: adjust is_ram check in register_savevm_live()
>>    migration-local: implementation of outgoing part
>>    migration-local: implementation of incoming part
>>    migration-local: add option to command line for local incoming
>>    hmp:add hmp_localhost_migration interface
>>
>>   Makefile.objs                 |    1 +
>>   arch_init.c                   |   110 +++++++++++++++++++
>>   block-migration.c             |    2 +-
>>   hmp-commands.hx               |   17 ++++
>>   hmp.c                         |   13 +++
>>   hmp.h                         |    1 +
>>   include/migration/migration.h |   32 +++++++
>>   include/sysemu/sysemu.h       |    1 +
>>   migration-local.c             |  228 +++++++++++++++++++++++++++++++++++++++++
>>   migration-unix.c              |   60 ++++++++++++
>>   migration.c                   |    8 --
>>   qapi-schema.json              |   14 +++
>>   qemu-options.hx               |    9 ++
>>   qmp-commands.hx               |   22 +++++
>>   savevm.c                      |   100 +++++++++++++++--
>>   vl.c                          |   14 +++
>>   16 files changed, 613 insertions(+), 19 deletions(-)
>>   create mode 100644 migration-local.c
>>
>


-- 
Lei

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2013-08-05  8:57 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-25 20:18 [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 01/12] migration: export MIG_STATE_xxx flags Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 02/12] savevm: export qemu_save_device_state() Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 03/12] rename is_active to is_block_active Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 04/12] arch_init: introduce ram_page_save() Lei Li
2013-08-02 19:40   ` Michael R. Hines
2013-08-05  2:49     ` Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 05/12] arch_init: introduce ram_save_local() Lei Li
2013-08-02 19:42   ` Michael R. Hines
2013-08-05  3:27     ` Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 06/12] arch_init: add save_local_setup to savevm_ram_handlers Lei Li
2013-08-02 19:43   ` Michael R. Hines
2013-07-25 20:18 ` [Qemu-devel] [PATCH 07/12] savevm: introduce qemu_savevm_local() Lei Li
2013-08-02 19:48   ` Michael R. Hines
2013-08-05  3:02     ` Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 08/12] savevm: adjust is_ram check in register_savevm_live() Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 09/12] migration-local: implementation of outgoing part Lei Li
2013-08-02 19:45   ` Michael R. Hines
2013-08-05  3:18     ` Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 10/12] migration-local: implementation of incoming part Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 11/12] migration-local: add option to commandline for incoming-local Lei Li
2013-08-02 19:46   ` Michael R. Hines
2013-08-05  3:21     ` Lei Li
2013-07-25 20:18 ` [Qemu-devel] [PATCH 12/12] hmp: add hmp_localhost_migration interface Lei Li
2013-08-02 19:47   ` Michael R. Hines
2013-08-05  3:22     ` Lei Li
2013-07-26  9:41 ` [Qemu-devel] [PATCH 0/12 RFC v2] Localhost migration Paolo Bonzini
2013-08-05  8:56   ` Lei Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).