On 28/02/12 15:51, Stefano Stabellini wrote:
- add an "is_ram" flag to SaveStateEntry;

- add an "is_ram" parameter to register_savevm_live;

- introduce a "save_devices" monitor command that can be used to save
the state of non-ram devices.

Signed-off-by: Stefano Stabellini<stefano.stabell...@eu.citrix.com>
---
  block-migration.c |    2 +-
  hmp-commands.hx   |   14 ++++++++++
  qmp-commands.hx   |   17 ++++++++++++
  savevm.c          |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
  sysemu.h          |    1 +
  vl.c              |    2 +-
  vmstate.h         |    1 +
  7 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/block-migration.c b/block-migration.c
index 4467468..d283fd0 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -722,6 +722,6 @@ void blk_mig_init(void)
      QSIMPLEQ_INIT(&block_mig_state.bmds_list);
      QSIMPLEQ_INIT(&block_mig_state.blk_list);

-    register_savevm_live(NULL, "block", 0, 1, block_set_params,
+    register_savevm_live(NULL, "block", 0, 1, 0, block_set_params,
                           block_save_live, NULL, block_load,&block_mig_state);
  }
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 64b3656..873abc9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -280,6 +280,20 @@ a snapshot with the same tag or ID, it is replaced. More 
info at
  ETEXI

      {
+        .name       = "save_devices",
+        .args_type  = "filename:F",
+        .params     = "filename",
+        .help       = "save the state of non-ram devices.",
+        .mhandler.cmd_new = do_save_device_state,
+    },
+
+STEXI
+@item save_devices @var{filename}
+@findex save_devices
+Save the state of non-ram devices.
+ETEXI
+
+    {
          .name       = "loadvm",
          .args_type  = "name:s",
          .params     = "tag|id",
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 705f704..619d9de 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -444,6 +444,23 @@ Note: inject-nmi is only supported for x86 guest 
currently, it will
  EQMP

      {
+        .name       = "save_devices",
+        .args_type  = "filename:F",
+        .params     = "filename",
+        .help       = "save the state of non-ram devices.",
+        .user_print = monitor_user_noop,       
+    .mhandler.cmd_new = do_save_device_state,
+    },
+
+SQMP
+save_devices
+-------
+
+Save the state of non-ram devices.
+
+EQMP
+
+    {
          .name       = "migrate",
          .args_type  = "detach:-d,blk:-b,inc:-i,uri:s",
          .params     = "[-d] [-b] [-i] uri",
diff --git a/savevm.c b/savevm.c
index 80be1ff..d0e62bb 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1177,6 +1177,7 @@ typedef struct SaveStateEntry {
      void *opaque;
      CompatEntry *compat;
      int no_migrate;
+    int is_ram;
  } SaveStateEntry;


@@ -1223,6 +1224,7 @@ int register_savevm_live(DeviceState *dev,
                           const char *idstr,
                           int instance_id,
                           int version_id,
+                         int is_ram,
                           SaveSetParamsHandler *set_params,
                           SaveLiveStateHandler *save_live_state,
                           SaveStateHandler *save_state,
@@ -1241,6 +1243,7 @@ int register_savevm_live(DeviceState *dev,
      se->opaque = opaque;
      se->vmsd = NULL;
      se->no_migrate = 0;
+    se->is_ram = is_ram;

      if (dev&&  dev->parent_bus&&  dev->parent_bus->info->get_dev_path) {
          char *id = dev->parent_bus->info->get_dev_path(dev);
@@ -1277,7 +1280,7 @@ int register_savevm(DeviceState *dev,
                      LoadStateHandler *load_state,
                      void *opaque)
  {
-    return register_savevm_live(dev, idstr, instance_id, version_id,
+    return register_savevm_live(dev, idstr, instance_id, version_id, 0,
                                  NULL, NULL, save_state, load_state, opaque);
  }

@@ -1728,6 +1731,43 @@ out:
      return ret;
  }

+static int qemu_save_device_state(Monitor *mon, QEMUFile *f)
+{
+    SaveStateEntry *se;
+
+    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
+    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+    cpu_synchronize_all_states();
+
+    QTAILQ_FOREACH(se,&savevm_handlers, entry) {
+        int len;
+
+        if (se->is_ram)
+            continue;
+        if (se->save_state == NULL&&  se->vmsd == NULL)
+            continue;
+
+        /* Section type */
+        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
+        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);
+
+        vmstate_save(f, se);
+    }
+
+    qemu_put_byte(f, QEMU_VM_EOF);
+
+    return qemu_file_get_error(f);
+}
+
  static SaveStateEntry *find_se(const char *idstr, int instance_id)
  {
      SaveStateEntry *se;
@@ -2109,6 +2149,36 @@ void do_savevm(Monitor *mon, const QDict *qdict)
          vm_start();
  }

+int do_save_device_state(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    int ret;
+    QEMUFile *f;
+    int saved_vm_running;
+    const char *filename = qdict_get_try_str(qdict, "filename");
+
+    saved_vm_running = runstate_is_running();
+    vm_stop(RUN_STATE_SAVE_VM);
+
+    f = qemu_fopen(filename, "wb");
+    if (!f) {
+        monitor_printf(mon, "Could not open VM state file\n");
+        ret = -1;
+        goto the_end;
+    }
+    ret = qemu_save_device_state(mon, f);
+    qemu_fclose(f);
+    if (ret<  0) {
+        monitor_printf(mon, "Error %d while writing VM\n", ret);
+        goto the_end;
+    }
+    ret = 0;
+
+ the_end:
+    if (saved_vm_running)
+        vm_start();
+    return ret;
+}
+
  int load_vmstate(const char *name)
  {
      BlockDriverState *bs, *bs_vm_state;
diff --git a/sysemu.h b/sysemu.h
index 98118cc..f4d5bf4 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -70,6 +70,7 @@ void qemu_remove_exit_notifier(Notifier *notify);
  void qemu_add_machine_init_done_notifier(Notifier *notify);

  void do_savevm(Monitor *mon, const QDict *qdict);
+int do_save_device_state(Monitor *mon, const QDict *qdict, QObject **ret_data);
  int load_vmstate(const char *name);
  void do_delvm(Monitor *mon, const QDict *qdict);
  void do_info_snapshots(Monitor *mon);
diff --git a/vl.c b/vl.c
index 1d4c350..5b2b84c 100644
--- a/vl.c
+++ b/vl.c
@@ -3393,7 +3393,7 @@ int main(int argc, char **argv, char **envp)
      default_drive(default_sdcard, snapshot, machine->use_scsi,
                    IF_SD, 0, SD_OPTS);

-    register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
+    register_savevm_live(NULL, "ram", 0, 4, 1, NULL, ram_save_live, NULL,
                           ram_load, NULL);

      if (nb_numa_nodes>  0) {
diff --git a/vmstate.h b/vmstate.h
index 9d3c49c..3cef117 100644
--- a/vmstate.h
+++ b/vmstate.h
@@ -44,6 +44,7 @@ int register_savevm_live(DeviceState *dev,
                           const char *idstr,
                           int instance_id,
                           int version_id,
+                         int is_ram,
                           SaveSetParamsHandler *set_params,
                           SaveLiveStateHandler *save_live_state,
                           SaveStateHandler *save_state,

Acked-by: Anthony PERARD <anthony.per...@citrix.com>

--
Anthony PERARD

Reply via email to