Re: [Qemu-devel] [PATCH v6 10/11] dump: Make kdump-compressed format available for 'dump-guest-memory'

2014-01-09 Thread Laszlo Ersek
comments below

On 01/05/14 08:27, Qiao Nuohan wrote:
 Make monitor command 'dump-guest-memory' be able to dump in kdump-compressed
 format. The command's usage:
 
   dump [-p] protocol [begin] [length] [format]
 
 'format' is used to specified the format of vmcore and can be:
 1. 'elf': ELF format, without compression
 2. 'kdump-zlib': kdump-compressed format, with zlib-compressed
 3. 'kdump-lzo': kdump-compressed format, with lzo-compressed
 4. 'kdump-snappy': kdump-compressed format, with snappy-compressed
 And without 'format' being set, it is same as 'elf'.
 
 Note:
   1. The kdump-compressed format is readable only with the crash utility and
  makedumpfile, and it can be smaller than the ELF format because of the
  compression support.
   2. The kdump-compressed format is the 6th edition.
 
 Signed-off-by: Qiao Nuohan qiaonuo...@cn.fujitsu.com
 ---
  dump.c   |  163 
 --
  hmp-commands.hx  |   12 +++-
  hmp.c|   23 +++-
  qapi-schema.json |   22 +++-
  qmp-commands.hx  |6 +-
  5 files changed, 212 insertions(+), 14 deletions(-)
 
 diff --git a/dump.c b/dump.c
 index 848957c..b4e79ff 100644
 --- a/dump.c
 +++ b/dump.c
 @@ -1398,6 +1398,70 @@ out:
  return ret;
  }
  
 +static int create_kdump_vmcore(DumpState *s)
 +{
 +int ret;
 +
 +/*
 + * the kdump-compressed format is:
 + *   File offset
 + *  +--+ 0x0
 + *  |main header (struct disk_dump_header) |
 + *  |--+ block 1
 + *  |sub header (struct kdump_sub_header)  |

Also including the note.

... Come to think of it, note_buf could actually be local to
create_headerXX(), no need to add it to DumpState.

 + *  |--+ block 2
 + *  |1st-dump_bitmap   |
 + *  |--+ block 2 + X blocks
 + *  |2nd-dump_bitmap   | (aligned by block)
 + *  |--+ block 2 + 2 * X blocks
 + *  |  page desc for pfn 0 (struct page_desc)  | (aligned by block)
 + *  |  page desc for pfn 1 (struct page_desc)  |
 + *  |: |
 + *  |  page desc for pfn Z (struct page_desc)  |
 + *  |--| (not aligned by block)
 + *  | page data (pfn 0)|
 + *  | page data (pfn 1)|
 + *  |: |
 + *  | page data (pfn Z)|
 + *  +--+ offset_eraseinfo

I think this offset_eraseinfo is a bit misleading, because we never
set that field in KdumpSubHeaderXX to nonzero, and we also never write
the trailing portion here.

Maybe a zero value of offset_eraseinfo implies presicely that the
portion marked below as : is never written, but still
offset_eraseinfo (== 0) doesn't match the end of the page data.

Also, using the same Z as final subscript for page data as for page
desc is misleading. There can be fewer, equal number of, and more page
data entries than page desc entries. We'll have fewer page data entries
if the guest has at least two zero pages. We'll have more page data
entries if the guest has no zero pages (because we dump exactly one zero
page data entry).

 + *  |: |
 + *  +--+
 + */
 +
 +if (s-flag_flatten) {
 +ret = write_start_flat_header(s-fd);
 +if (ret  0) {
 +return -1;
 +}
 +}
 +
 +ret = write_dump_header(s);
 +if (ret  0) {
 +return -1;
 +}
 +
 +ret = write_dump_bitmap(s);
 +if (ret  0) {
 +return -1;
 +}
 +
 +ret = write_dump_pages(s);
 +if (ret  0) {
 +return -1;
 +}
 +
 +if (s-flag_flatten) {
 +ret = write_end_flat_header(s-fd);
 +if (ret  0) {
 +return -1;
 +}
 +}
 +
 +dump_completed(s);
 +
 +return 0;
 +}
 +
  static ram_addr_t get_start_block(DumpState *s)
  {
  GuestPhysBlock *block;
 @@ -1426,7 +1490,27 @@ static ram_addr_t get_start_block(DumpState *s)
  return -1;
  }
  
 -static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
 +static bool use_flatten_format(int fd)
 +{
 +if (lseek(fd, 0, SEEK_SET)  0) {
 +return true;
 +}
 +
 +return false;
 +}
 +
 +static void get_max_mapnr(DumpState *s)
 +{
 +MemoryMapping *memory_mapping;
 +
 +QTAILQ_FOREACH(memory_mapping, s-list.head, next) {
 +s-max_mapnr = paddr_to_pfn(memory_mapping-phys_addr +
 +memory_mapping-length, s-page_shift);
 +}
 +}

I'm a bit confused about the difference between 

[Qemu-devel] [PATCH v6 10/11] dump: Make kdump-compressed format available for 'dump-guest-memory'

2014-01-05 Thread Qiao Nuohan
Make monitor command 'dump-guest-memory' be able to dump in kdump-compressed
format. The command's usage:

  dump [-p] protocol [begin] [length] [format]

'format' is used to specified the format of vmcore and can be:
1. 'elf': ELF format, without compression
2. 'kdump-zlib': kdump-compressed format, with zlib-compressed
3. 'kdump-lzo': kdump-compressed format, with lzo-compressed
4. 'kdump-snappy': kdump-compressed format, with snappy-compressed
And without 'format' being set, it is same as 'elf'.

Note:
  1. The kdump-compressed format is readable only with the crash utility and
 makedumpfile, and it can be smaller than the ELF format because of the
 compression support.
  2. The kdump-compressed format is the 6th edition.

Signed-off-by: Qiao Nuohan qiaonuo...@cn.fujitsu.com
---
 dump.c   |  163 --
 hmp-commands.hx  |   12 +++-
 hmp.c|   23 +++-
 qapi-schema.json |   22 +++-
 qmp-commands.hx  |6 +-
 5 files changed, 212 insertions(+), 14 deletions(-)

diff --git a/dump.c b/dump.c
index 848957c..b4e79ff 100644
--- a/dump.c
+++ b/dump.c
@@ -1398,6 +1398,70 @@ out:
 return ret;
 }
 
+static int create_kdump_vmcore(DumpState *s)
+{
+int ret;
+
+/*
+ * the kdump-compressed format is:
+ *   File offset
+ *  +--+ 0x0
+ *  |main header (struct disk_dump_header) |
+ *  |--+ block 1
+ *  |sub header (struct kdump_sub_header)  |
+ *  |--+ block 2
+ *  |1st-dump_bitmap   |
+ *  |--+ block 2 + X blocks
+ *  |2nd-dump_bitmap   | (aligned by block)
+ *  |--+ block 2 + 2 * X blocks
+ *  |  page desc for pfn 0 (struct page_desc)  | (aligned by block)
+ *  |  page desc for pfn 1 (struct page_desc)  |
+ *  |: |
+ *  |  page desc for pfn Z (struct page_desc)  |
+ *  |--| (not aligned by block)
+ *  | page data (pfn 0)|
+ *  | page data (pfn 1)|
+ *  |: |
+ *  | page data (pfn Z)|
+ *  +--+ offset_eraseinfo
+ *  |: |
+ *  +--+
+ */
+
+if (s-flag_flatten) {
+ret = write_start_flat_header(s-fd);
+if (ret  0) {
+return -1;
+}
+}
+
+ret = write_dump_header(s);
+if (ret  0) {
+return -1;
+}
+
+ret = write_dump_bitmap(s);
+if (ret  0) {
+return -1;
+}
+
+ret = write_dump_pages(s);
+if (ret  0) {
+return -1;
+}
+
+if (s-flag_flatten) {
+ret = write_end_flat_header(s-fd);
+if (ret  0) {
+return -1;
+}
+}
+
+dump_completed(s);
+
+return 0;
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
 GuestPhysBlock *block;
@@ -1426,7 +1490,27 @@ static ram_addr_t get_start_block(DumpState *s)
 return -1;
 }
 
-static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
+static bool use_flatten_format(int fd)
+{
+if (lseek(fd, 0, SEEK_SET)  0) {
+return true;
+}
+
+return false;
+}
+
+static void get_max_mapnr(DumpState *s)
+{
+MemoryMapping *memory_mapping;
+
+QTAILQ_FOREACH(memory_mapping, s-list.head, next) {
+s-max_mapnr = paddr_to_pfn(memory_mapping-phys_addr +
+memory_mapping-length, s-page_shift);
+}
+}
+
+static int dump_init(DumpState *s, int fd, bool has_format,
+ DumpGuestMemoryFormat format, bool paging, bool 
has_filter,
  int64_t begin, int64_t length, Error **errp)
 {
 CPUState *cpu;
@@ -1494,6 +1578,44 @@ static int dump_init(DumpState *s, int fd, bool paging, 
bool has_filter,
 qemu_get_guest_simple_memory_mapping(s-list, s-guest_phys_blocks);
 }
 
+/* init for kdump-compressed format */
+if (has_format  format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
+switch (format) {
+case DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB:
+s-flag_compress = DUMP_DH_COMPRESSED_ZLIB;
+break;
+
+case DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO:
+s-flag_compress = DUMP_DH_COMPRESSED_LZO;
+break;
+
+case DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY:
+s-flag_compress = DUMP_DH_COMPRESSED_SNAPPY;
+break;
+
+default:
+s-flag_compress = 0;
+}
+
+/*
+ * check to see if fd is available to seek.
+ * if not, flatten format is used