diff mbox

[RFC,1/3] memory: Add dump-pc-mem command for checkpointing

Message ID d2e6189248c6e4c2d04f849d57409952ff79da94.1429272036.git.bv.trach@gmail.com
State New
Headers show

Commit Message

Bohdan Trach April 17, 2015, 12:13 p.m. UTC
From: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>

dump-pc-mem command is added for checkpointing guest memory to
file. Only system RAM region is saved. This checkpoint is later used to
recover unchanged pages.

Signed-off-by: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
---
 arch_init.c      | 19 +++++++++++++++++++
 hmp-commands.hx  | 16 ++++++++++++++++
 hmp.c            |  9 +++++++++
 hmp.h            |  1 +
 qapi-schema.json | 11 +++++++++++
 qmp-commands.hx  | 19 +++++++++++++++++++
 6 files changed, 75 insertions(+)

Comments

Eric Blake April 17, 2015, 1:53 p.m. UTC | #1
On 04/17/2015 06:13 AM, Bohdan Trach wrote:
> From: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
> 
> dump-pc-mem command is added for checkpointing guest memory to
> file. Only system RAM region is saved. This checkpoint is later used to
> recover unchanged pages.
> 
> Signed-off-by: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
> ---

> 
> +void qmp_dump_pc_ram(const char *file, Error **errp) {
> +
> +    int rc;
> +    int fd;
> +    fd = open(file,

Please use qemu_open() rather than raw open(), so that your command
automatically supports /dev/fdset/nnn notation for reusing a file
descriptor passed in via SCM_RIGHTS.

> +++ b/qapi-schema.json
> @@ -3648,3 +3648,14 @@
>  # Since: 2.1
>  ##
>  { 'command': 'rtc-reset-reinjection' }
> +
> +##
> +# @dump-pc-ram:
> +#
> +# Checkpoints guest.

The whole guest, or just guest memory?

> +#
> +# @file: the file to save the memory to as binary data
> +#
> +# Returns: Nothing on success

Missing a 'Since: 2.4' designation.

> +##
> +{ 'command': 'dump-pc-ram', 'data': {'file': 'str'} }
Bohdan Trach April 18, 2015, 7:40 a.m. UTC | #2
Thank You for the review.

Please see comments inline.

On 04/17/2015 03:53 PM, Eric Blake wrote:
> On 04/17/2015 06:13 AM, Bohdan Trach wrote:
>> From: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
>>
>> dump-pc-mem command is added for checkpointing guest memory to
>> file. Only system RAM region is saved. This checkpoint is later used to
>> recover unchanged pages.
>>
>> Signed-off-by: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
>> ---
> 
>>
>> +void qmp_dump_pc_ram(const char *file, Error **errp) {
>> +
>> +    int rc;
>> +    int fd;
>> +    fd = open(file,
> 
> Please use qemu_open() rather than raw open(), so that your command
> automatically supports /dev/fdset/nnn notation for reusing a file
> descriptor passed in via SCM_RIGHTS.
> 

OK, this will be fixed.

>> +++ b/qapi-schema.json
>> @@ -3648,3 +3648,14 @@
>>  # Since: 2.1
>>  ##
>>  { 'command': 'rtc-reset-reinjection' }
>> +
>> +##
>> +# @dump-pc-ram:
>> +#
>> +# Checkpoints guest.
> 
> The whole guest, or just guest memory?
> 

dump-pc-ram command currently writes "pc.ram" MemoryRegion to the
specified file.

>> +#
>> +# @file: the file to save the memory to as binary data
>> +#
>> +# Returns: Nothing on success
> 
> Missing a 'Since: 2.4' designation.
> 

OK, I'll add it.
Dr. David Alan Gilbert Nov. 16, 2015, 4:46 p.m. UTC | #3
* Bohdan Trach (bv.trach@gmail.com) wrote:
> From: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
> 
> dump-pc-mem command is added for checkpointing guest memory to
> file. Only system RAM region is saved. This checkpoint is later used to
> recover unchanged pages.

Why not just use the 'dump_guest_memory' commands; they dump it in interesting
existing formats; they have headers in the files as well rather than just
a raw blob of data.
If you wanted to restrict to only certain RAM blocks, then I'd suggest adding
a feature to that existing command.
You might also find that you want other RAMBlocks as well, for example where
RAM is added using hot plu, those are separate RAM blocks.

Dave

> Signed-off-by: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
> ---
>  arch_init.c      | 19 +++++++++++++++++++
>  hmp-commands.hx  | 16 ++++++++++++++++
>  hmp.c            |  9 +++++++++
>  hmp.h            |  1 +
>  qapi-schema.json | 11 +++++++++++
>  qmp-commands.hx  | 19 +++++++++++++++++++
>  6 files changed, 75 insertions(+)
> 
> diff --git a/arch_init.c b/arch_init.c
> index 4c8fcee..b8a4fb1 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -603,6 +603,25 @@ static void migration_bitmap_sync(void)
>      }
>  }
>  
> +void qmp_dump_pc_ram(const char *file, Error **errp) {
> +
> +    int rc;
> +    int fd;
> +    fd = open(file,
> +              O_CREAT|O_WRONLY,
> +              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
> +    assert(-1 != fd);
> +
> +    RAMBlock *block = QLIST_FIRST_RCU(&ram_list.blocks);
> +    uint64_t offset;
> +    for (offset=0; offset<ram_size; offset+=TARGET_PAGE_SIZE) {
> +        rc = write(fd, block->host+offset, TARGET_PAGE_SIZE);
> +        assert(TARGET_PAGE_SIZE == rc);
> +    }
> +    rc = close(fd);
> +    assert(0 == rc);
> +}
> +
>  /**
>   * ram_save_page: Send the given page to the stream
>   *
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 3089533..0c47a4f 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1043,6 +1043,22 @@ gdb. Without -z|-l|-s, the dump format is ELF.
>  ETEXI
>  
>      {
> +        .name       = "dump-pc-ram",
> +        .args_type  = "filename:F",
> +        .params     = "filename",
> +        .help       = "dump pc ram to file",
> +        .mhandler.cmd = hmp_dump_pc_ram,
> +    },
> +
> +
> +STEXI
> +@item dump-pc-ram
> +@findex dump-guest-memory
> +Dump pc ram to file.
> +  filename: dump file name
> +ETEXI
> +
> +    {
>          .name       = "snapshot_blkdev",
>          .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
>          .params     = "[-n] device [new-image-file] [format]",
> diff --git a/hmp.c b/hmp.c
> index f31ae27..5e27dd8 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1473,6 +1473,15 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
>      g_free(prot);
>  }
>  
> +void hmp_dump_pc_ram(Monitor *mon, const QDict *qdict)
> +{
> +    Error *errp = NULL;
> +    const char *file = qdict_get_str(qdict, "filename");
> +
> +    qmp_dump_pc_ram(file, &errp);
> +    hmp_handle_error(mon, &errp);
> +}
> +
>  void hmp_netdev_add(Monitor *mon, const QDict *qdict)
>  {
>      Error *err = NULL;
> diff --git a/hmp.h b/hmp.h
> index 2b9308b..805a71b 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -79,6 +79,7 @@ void hmp_block_job_complete(Monitor *mon, const QDict *qdict);
>  void hmp_migrate(Monitor *mon, const QDict *qdict);
>  void hmp_device_del(Monitor *mon, const QDict *qdict);
>  void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
> +void hmp_dump_pc_ram(Monitor *mon, const QDict *qdict);
>  void hmp_netdev_add(Monitor *mon, const QDict *qdict);
>  void hmp_netdev_del(Monitor *mon, const QDict *qdict);
>  void hmp_getfd(Monitor *mon, const QDict *qdict);
> diff --git a/qapi-schema.json b/qapi-schema.json
> index ac9594d..338bfd3 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3648,3 +3648,14 @@
>  # Since: 2.1
>  ##
>  { 'command': 'rtc-reset-reinjection' }
> +
> +##
> +# @dump-pc-ram:
> +#
> +# Checkpoints guest.
> +#
> +# @file: the file to save the memory to as binary data
> +#
> +# Returns: Nothing on success
> +##
> +{ 'command': 'dump-pc-ram', 'data': {'file': 'str'} }
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 3a42ad0..0be3c42 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -854,6 +854,25 @@ Notes:
>  EQMP
>  
>      {
> +        .name       = "dump-pc-ram",
> +        .args_type  = "file:s",
> +        .params     = "file",
> +        .help       = "dump pc ram to file",
> +        .user_print = monitor_user_noop,
> +        .mhandler.cmd_new = qmp_marshal_input_dump_pc_ram,
> +    },
> +
> +SQMP
> +dump
> +
> +
> +Dump pc ram to file.
> +
> +Arguments:
> +
> +EQMP
> +
> +    {
>          .name       = "query-dump-guest-memory-capability",
>          .args_type  = "",
>      .mhandler.cmd_new = qmp_marshal_input_query_dump_guest_memory_capability,
> -- 
> 2.0.5
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
Bohdan Trach Nov. 17, 2015, 3:38 p.m. UTC | #4
Hi David, thank you for the feedback!

On 11/16/2015 05:46 PM, Dr. David Alan Gilbert wrote:
> * Bohdan Trach (bv.trach@gmail.com) wrote:
>> From: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
>>
>> dump-pc-mem command is added for checkpointing guest memory to
>> file. Only system RAM region is saved. This checkpoint is later used to
>> recover unchanged pages.
> 
> Why not just use the 'dump_guest_memory' commands; they dump it in interesting
> existing formats; they have headers in the files as well rather than just
> a raw blob of data.
> If you wanted to restrict to only certain RAM blocks, then I'd suggest adding
> a feature to that existing command.
> You might also find that you want other RAMBlocks as well, for example where
> RAM is added using hot plu, those are separate RAM blocks.

We will try to rework these patches to use existing formats. Current
format was used because it is extremely simple to work with. The
restriction of saving only 'pc.ram' RAMBlock is just the consequence
of this design choice.

> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
>
Dr. David Alan Gilbert Nov. 17, 2015, 4:02 p.m. UTC | #5
* Bohdan Trach (bohdan.trach@mailbox.tu-dresden.de) wrote:
> Hi David, thank you for the feedback!

No problem, sorry for the delay,

> On 11/16/2015 05:46 PM, Dr. David Alan Gilbert wrote:
> > * Bohdan Trach (bv.trach@gmail.com) wrote:
> >> From: Bohdan Trach <bohdan.trach@mailbox.tu-dresden.de>
> >>
> >> dump-pc-mem command is added for checkpointing guest memory to
> >> file. Only system RAM region is saved. This checkpoint is later used to
> >> recover unchanged pages.
> > 
> > Why not just use the 'dump_guest_memory' commands; they dump it in interesting
> > existing formats; they have headers in the files as well rather than just
> > a raw blob of data.
> > If you wanted to restrict to only certain RAM blocks, then I'd suggest adding
> > a feature to that existing command.
> > You might also find that you want other RAMBlocks as well, for example where
> > RAM is added using hot plu, those are separate RAM blocks.
> 
> We will try to rework these patches to use existing formats. Current
> format was used because it is extremely simple to work with. The
> restriction of saving only 'pc.ram' RAMBlock is just the consequence
> of this design choice.

I think the ELF one should actually turn out to be the easiest; there's
probably some existing ELF code you can find in the QEMU code base
to make it easier to parse, but once you find the start of the block
it should then be contiguous.

Dave


> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> > 
> 
> -- 
> With best regards,
> Bohdan Trach
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
diff mbox

Patch

diff --git a/arch_init.c b/arch_init.c
index 4c8fcee..b8a4fb1 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -603,6 +603,25 @@  static void migration_bitmap_sync(void)
     }
 }
 
+void qmp_dump_pc_ram(const char *file, Error **errp) {
+
+    int rc;
+    int fd;
+    fd = open(file,
+              O_CREAT|O_WRONLY,
+              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+    assert(-1 != fd);
+
+    RAMBlock *block = QLIST_FIRST_RCU(&ram_list.blocks);
+    uint64_t offset;
+    for (offset=0; offset<ram_size; offset+=TARGET_PAGE_SIZE) {
+        rc = write(fd, block->host+offset, TARGET_PAGE_SIZE);
+        assert(TARGET_PAGE_SIZE == rc);
+    }
+    rc = close(fd);
+    assert(0 == rc);
+}
+
 /**
  * ram_save_page: Send the given page to the stream
  *
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 3089533..0c47a4f 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1043,6 +1043,22 @@  gdb. Without -z|-l|-s, the dump format is ELF.
 ETEXI
 
     {
+        .name       = "dump-pc-ram",
+        .args_type  = "filename:F",
+        .params     = "filename",
+        .help       = "dump pc ram to file",
+        .mhandler.cmd = hmp_dump_pc_ram,
+    },
+
+
+STEXI
+@item dump-pc-ram
+@findex dump-guest-memory
+Dump pc ram to file.
+  filename: dump file name
+ETEXI
+
+    {
         .name       = "snapshot_blkdev",
         .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
         .params     = "[-n] device [new-image-file] [format]",
diff --git a/hmp.c b/hmp.c
index f31ae27..5e27dd8 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1473,6 +1473,15 @@  void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
     g_free(prot);
 }
 
+void hmp_dump_pc_ram(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+    const char *file = qdict_get_str(qdict, "filename");
+
+    qmp_dump_pc_ram(file, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
 void hmp_netdev_add(Monitor *mon, const QDict *qdict)
 {
     Error *err = NULL;
diff --git a/hmp.h b/hmp.h
index 2b9308b..805a71b 100644
--- a/hmp.h
+++ b/hmp.h
@@ -79,6 +79,7 @@  void hmp_block_job_complete(Monitor *mon, const QDict *qdict);
 void hmp_migrate(Monitor *mon, const QDict *qdict);
 void hmp_device_del(Monitor *mon, const QDict *qdict);
 void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
+void hmp_dump_pc_ram(Monitor *mon, const QDict *qdict);
 void hmp_netdev_add(Monitor *mon, const QDict *qdict);
 void hmp_netdev_del(Monitor *mon, const QDict *qdict);
 void hmp_getfd(Monitor *mon, const QDict *qdict);
diff --git a/qapi-schema.json b/qapi-schema.json
index ac9594d..338bfd3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3648,3 +3648,14 @@ 
 # Since: 2.1
 ##
 { 'command': 'rtc-reset-reinjection' }
+
+##
+# @dump-pc-ram:
+#
+# Checkpoints guest.
+#
+# @file: the file to save the memory to as binary data
+#
+# Returns: Nothing on success
+##
+{ 'command': 'dump-pc-ram', 'data': {'file': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 3a42ad0..0be3c42 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -854,6 +854,25 @@  Notes:
 EQMP
 
     {
+        .name       = "dump-pc-ram",
+        .args_type  = "file:s",
+        .params     = "file",
+        .help       = "dump pc ram to file",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = qmp_marshal_input_dump_pc_ram,
+    },
+
+SQMP
+dump
+
+
+Dump pc ram to file.
+
+Arguments:
+
+EQMP
+
+    {
         .name       = "query-dump-guest-memory-capability",
         .args_type  = "",
     .mhandler.cmd_new = qmp_marshal_input_query_dump_guest_memory_capability,