All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
@ 2013-07-09  7:30 Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 1/9] dump: Add argument to write_elfxx_notes Qiao Nuohan
                   ` (10 more replies)
  0 siblings, 11 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

Hi, all

The last version is here:
http://lists.gnu.org/archive/html/qemu-devel/2013-05/msg03866.html

Command 'dump-guest-memory' was introduced to dump guest's memory. But the
vmcore's format is only elf32 or elf64. The message is here:
http://lists.gnu.org/archive/html/qemu-devel/2012-04/msg03379.html

Compared with migration, the missing of compression feature means regression
to 'dump-guest-memory'. So we post these patches to make 'dump-guest-memory' be
able to dump guest's in kdump-compressed format. Then vmcore can be much
smaller, and easily to be delivered.

The kdump-compressed format is *linux specific* *linux standard* crash dump
format used in kdump framework. The kdump-compressed format is readable only
with the crash utility, and it can be smaller than the ELF format because of
the compression support. To get more detailed information about
kdump-compressed format, please refer to the following URL:
http://sourceforge.net/projects/makedumpfile/

Note, similar to 'dump-guest-memory':
1. The guest should be x86 or x86_64. The other arch is not supported now.
2. If the OS is in the second kernel, gdb may not work well, and crash can
   work by specifying '--machdep phys_addr=xxx' in the command line. The
   reason is that the second kernel will update the page table, and we can
   not get the page table for the first kernel.
3. The cpu's state is stored in QEMU note.
4. The vmcore are able to be compressed with zlib, lzo or snappy. zlib is
   available by default, and option '--enable-lzo' or '--enable-snappy'
   should be specified with 'configure' to make lzo or snappy available.

Changelog:
Changes from v4 to v5:
1. using flatten format to avoid using temporary files according to Stefan's
   comments
2. Address Andreas's comments about coding style

Changes from v3 to v4:
1. change to avoid conflict with Andreas's patches
2. rebase

Changes from v2 to v3:
1. Address Eric's comment

Changes from v1 to v2:
1. Address Eric & Daniel's comment: fix manner of string copy.
2. Address Eric's comment: replace reinventing new constants by using the
   ready-made ones accoring.
3. Address Andreas's comment: remove useless include.

Qiao Nuohan (9):
  dump: Add argument to write_elfxx_notes
  dump: Add API to write header of flatten format
  dump: Add API to write vmcore
  dump: Add API to write elf notes to buffer
  dump: add API to write dump header
  dump: Add API to write dump_bitmap
  dump: Add APIs to operate DataCache
  dump: Add API to write dump pages
  dump: Make kdump-compressed format available for 'dump-guest-memory'

 configure             |   50 +++
 dump.c                |  873 ++++++++++++++++++++++++++++++++++++++++++++++++-
 hmp-commands.hx       |   12 +-
 hmp.c                 |   23 ++-
 include/sysemu/dump.h |  127 +++++++
 qapi-schema.json      |   22 ++-
 qmp-commands.hx       |    6 +-
 7 files changed, 1088 insertions(+), 25 deletions(-)

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

* [Qemu-devel] [PATCH v5 1/9] dump: Add argument to write_elfxx_notes
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 2/9] dump: Add API to write header of flatten format Qiao Nuohan
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

write_elf32_notes/wirte_elf64_notes use fd_write_vmcore to write elf notes to
vmcore. Adding argument "WriteCoreDumpFunction f" makes it available to choose
the way of writing elf notes when calling these two functions.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/dump.c b/dump.c
index c812cfa..4e478b1 100644
--- a/dump.c
+++ b/dump.c
@@ -273,7 +273,7 @@ static inline int cpu_index(CPUState *cpu)
     return cpu->cpu_index + 1;
 }
 
-static int write_elf64_notes(DumpState *s)
+static int write_elf64_notes(WriteCoreDumpFunction f, DumpState *s)
 {
     CPUArchState *env;
     CPUState *cpu;
@@ -283,7 +283,7 @@ static int write_elf64_notes(DumpState *s)
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         cpu = ENV_GET_CPU(env);
         id = cpu_index(cpu);
-        ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s);
+        ret = cpu_write_elf64_note(f, cpu, id, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write elf notes.\n");
             return -1;
@@ -291,7 +291,7 @@ static int write_elf64_notes(DumpState *s)
     }
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s);
+        ret = cpu_write_elf64_qemunote(f, cpu, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write CPU status.\n");
             return -1;
@@ -325,7 +325,7 @@ static int write_elf32_note(DumpState *s)
     return 0;
 }
 
-static int write_elf32_notes(DumpState *s)
+static int write_elf32_notes(WriteCoreDumpFunction f, DumpState *s)
 {
     CPUArchState *env;
     CPUState *cpu;
@@ -335,7 +335,7 @@ static int write_elf32_notes(DumpState *s)
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         cpu = ENV_GET_CPU(env);
         id = cpu_index(cpu);
-        ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s);
+        ret = cpu_write_elf32_note(f, cpu, id, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write elf notes.\n");
             return -1;
@@ -343,7 +343,7 @@ static int write_elf32_notes(DumpState *s)
     }
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s);
+        ret = cpu_write_elf32_qemunote(f, cpu, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write CPU status.\n");
             return -1;
@@ -562,7 +562,7 @@ static int dump_begin(DumpState *s)
         }
 
         /* write notes to vmcore */
-        if (write_elf64_notes(s) < 0) {
+        if (write_elf64_notes(fd_write_vmcore, s) < 0) {
             return -1;
         }
 
@@ -585,7 +585,7 @@ static int dump_begin(DumpState *s)
         }
 
         /* write notes to vmcore */
-        if (write_elf32_notes(s) < 0) {
+        if (write_elf32_notes(fd_write_vmcore, s) < 0) {
             return -1;
         }
     }
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 2/9] dump: Add API to write header of flatten format
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 1/9] dump: Add argument to write_elfxx_notes Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-16  2:06   ` Stefan Hajnoczi
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 3/9] dump: Add API to write vmcore Qiao Nuohan
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

flatten format may be used when writing kdump-compressed format. To get more
detailed information about flatten format of kdump-compressed format, please
refer to the following URL:
http://sourceforge.net/projects/makedumpfile/

The two functions here are used to write start flat header and end flat header
to vmcore, and they will be called later if flatten format is used.

struct MakedumpfileHeader stored at the head of vmcore is used to indicate the
vmcore is in flatten format.

struct MakedumpfileHeader {
    char signature[16];     /* = "makedumpfile" */
    int64_t type;           /* = 1 */
    int64_t version;        /* = 1 */
};

And struct MakedumpfileDataHeader, with offset and buf_size set to -1, is used
to indicate the end of vmcore in flatten format.

struct MakedumpfileDataHeader {
    int64_t offset;         /* = -1 */
    int64_t buf_size;       /* = -1 */
};

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c                |   40 ++++++++++++++++++++++++++++++++++++++++
 include/sysemu/dump.h |   17 +++++++++++++++++
 2 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/dump.c b/dump.c
index 4e478b1..f04d4fc 100644
--- a/dump.c
+++ b/dump.c
@@ -674,6 +674,46 @@ static int create_vmcore(DumpState *s)
     return 0;
 }
 
+static int write_start_flat_header(int fd)
+{
+    char buf[MAX_SIZE_MDF_HEADER];
+    MakedumpfileHeader mh;
+
+    memset(&mh, 0, sizeof(mh));
+    strncpy(mh.signature, MAKEDUMPFILE_SIGNATURE,
+            strlen(MAKEDUMPFILE_SIGNATURE));
+
+    mh.type = cpu_to_be64(TYPE_FLAT_HEADER);
+    mh.version = cpu_to_be64(VERSION_FLAT_HEADER);
+
+    memset(buf, 0, sizeof(buf));
+    memcpy(buf, &mh, sizeof(mh));
+
+    size_t written_size;
+    written_size = qemu_write_full(fd, buf, sizeof(buf));
+    if (written_size != sizeof(buf)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_end_flat_header(int fd)
+{
+    MakedumpfileDataHeader mdh;
+
+    mdh.offset = END_FLAG_FLAT_HEADER;
+    mdh.buf_size = END_FLAG_FLAT_HEADER;
+
+    size_t written_size;
+    written_size = qemu_write_full(fd, &mdh, sizeof(mdh));
+    if (written_size != sizeof(mdh)) {
+        return -1;
+    }
+
+    return 0;
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index b8c770f..81cbaa8 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -14,12 +14,29 @@
 #ifndef DUMP_H
 #define DUMP_H
 
+#define MAKEDUMPFILE_SIGNATURE      "makedumpfile"
+#define MAX_SIZE_MDF_HEADER         (4096) /* max size of makedumpfile_header */
+#define TYPE_FLAT_HEADER            (1)    /* type of flattened format */
+#define VERSION_FLAT_HEADER         (1)    /* version of flattened format */
+#define END_FLAG_FLAT_HEADER        (-1)
+
 typedef struct ArchDumpInfo {
     int d_machine;  /* Architecture */
     int d_endian;   /* ELFDATA2LSB or ELFDATA2MSB */
     int d_class;    /* ELFCLASS32 or ELFCLASS64 */
 } ArchDumpInfo;
 
+typedef struct QEMU_PACKED MakedumpfileHeader {
+    char signature[16];     /* = "makedumpfile" */
+    int64_t type;
+    int64_t version;
+} MakedumpfileHeader;
+
+typedef struct QEMU_PACKED MakedumpfileDataHeader {
+    int64_t offset;
+    int64_t buf_size;
+} MakedumpfileDataHeader;
+
 int cpu_get_dump_info(ArchDumpInfo *info);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 3/9] dump: Add API to write vmcore
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 1/9] dump: Add argument to write_elfxx_notes Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 2/9] dump: Add API to write header of flatten format Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 4/9] dump: Add API to write elf notes to buffer Qiao Nuohan
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

Function is used to write vmcore. If flag_flatten is specified, flatten format
will be used. In flatten format, data is written block by block in vmcore.
struct MakedumpfileDataHeader is used to indicate the offset and size of a data
block.

struct MakedumpfileDataHeader {
    int64_t offset;
    int64_t buf_size;
};

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/dump.c b/dump.c
index f04d4fc..6f14b8d 100644
--- a/dump.c
+++ b/dump.c
@@ -714,6 +714,34 @@ static int write_end_flat_header(int fd)
     return 0;
 }
 
+static int write_buffer(int fd, bool flag_flatten, off_t offset, void *buf,
+                        size_t size)
+{
+    size_t written_size;
+    MakedumpfileDataHeader mdh;
+
+    if (flag_flatten) {
+        mdh.offset = cpu_to_be64(offset);
+        mdh.buf_size = cpu_to_be64(size);
+
+        written_size = qemu_write_full(fd, &mdh, sizeof(mdh));
+        if (written_size != sizeof(mdh)) {
+            return -1;
+        }
+    } else {
+        if (lseek(fd, offset, SEEK_SET) < 0) {
+            return -1;
+        }
+    }
+
+    written_size = qemu_write_full(fd, buf, size);
+    if (written_size != size) {
+        return -1;
+    }
+
+    return 0;
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 4/9] dump: Add API to write elf notes to buffer
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (2 preceding siblings ...)
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 3/9] dump: Add API to write vmcore Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 5/9] dump: add API to write dump header Qiao Nuohan
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

the function can be used by write_elf32_notes/write_elf64_notes. If
fd_write_vmcore is called by write_elf32_notes/write_elf64_notes, elf notes will
be written to vmcore by fd_write_vmcore directly. Instead, buf_write_note will
write elf notes to opaque->note_buf. And the elf notes stored in
opaque->note_buf will be used later.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/dump.c b/dump.c
index 6f14b8d..d7b3624 100644
--- a/dump.c
+++ b/dump.c
@@ -75,6 +75,9 @@ typedef struct DumpState {
     int64_t begin;
     int64_t length;
     Error **errp;
+
+    void *note_buf;
+    size_t note_buf_offset;
 } DumpState;
 
 static int dump_cleanup(DumpState *s)
@@ -742,6 +745,22 @@ static int write_buffer(int fd, bool flag_flatten, off_t offset, void *buf,
     return 0;
 }
 
+static int buf_write_note(void *buf, size_t size, void *opaque)
+{
+    DumpState *s = opaque;
+
+    /* note_buf is not enough */
+    if (s->note_buf_offset + size > s->note_size) {
+        return -1;
+    }
+
+    memcpy(s->note_buf + s->note_buf_offset, buf, size);
+
+    s->note_buf_offset += size;
+
+    return 0;
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 5/9] dump: add API to write dump header
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (3 preceding siblings ...)
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 4/9] dump: Add API to write elf notes to buffer Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-16  2:18   ` Stefan Hajnoczi
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap Qiao Nuohan
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

the functions are used to write header of kdump-compressed format to vmcore.
Header of kdump-compressed format includes:
1. common header: DiskDumpHeader32 / DiskDumpHeader64
2. sub header: KdumpSubHeader32 / KdumpSubHeader64
3. extra information: only elf notes here

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c                |  164 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/dump.h |   79 +++++++++++++++++++++++
 2 files changed, 243 insertions(+), 0 deletions(-)

diff --git a/dump.c b/dump.c
index d7b3624..cb2f866 100644
--- a/dump.c
+++ b/dump.c
@@ -76,8 +76,15 @@ typedef struct DumpState {
     int64_t length;
     Error **errp;
 
+    bool flag_flatten;
+    uint32_t nr_cpus;
+    size_t page_size;
+    size_t max_mapnr;
+    size_t len_dump_bitmap;
     void *note_buf;
     size_t note_buf_offset;
+    off_t offset_dump_bitmap;
+    off_t offset_page;
 } DumpState;
 
 static int dump_cleanup(DumpState *s)
@@ -761,6 +768,163 @@ static int buf_write_note(void *buf, size_t size, void *opaque)
     return 0;
 }
 
+/* write common header, sub header and elf note to vmcore */
+static int create_header32(DumpState *s)
+{
+    int ret = 0;
+    DiskDumpHeader32 *dh;
+    KdumpSubHeader32 *kh;
+    size_t size;
+
+    /* write common header, the version of kdump-compressed format is 5th */
+    size = sizeof(DiskDumpHeader32);
+    dh = g_malloc0(size);
+
+    strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
+    dh->header_version = 5;
+    dh->block_size = s->page_size;
+    dh->sub_hdr_size = sizeof(struct KdumpSubHeader32) + s->note_size;
+    dh->sub_hdr_size = divideup(dh->sub_hdr_size, dh->block_size);
+    dh->max_mapnr = s->max_mapnr;
+    dh->nr_cpus = s->nr_cpus;
+    dh->bitmap_blocks = divideup(s->len_dump_bitmap, s->page_size);
+    memcpy(&(dh->utsname.machine), "i686", 4);
+
+    if (write_buffer(s->fd, s->flag_flatten, 0, dh, size) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    /* write sub header */
+    size = sizeof(KdumpSubHeader32);
+    kh = g_malloc0(size);
+
+    kh->phys_base = PHYS_BASE;
+    kh->dump_level = DUMP_LEVEL;
+
+    kh->offset_note = DISKDUMP_HEADER_BLOCKS * dh->block_size + size;
+    kh->note_size = s->note_size;
+
+    if (write_buffer(s->fd, s->flag_flatten, dh->block_size, kh, size) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    /* write note */
+    s->note_buf = g_malloc(s->note_size);
+    s->note_buf_offset = 0;
+
+    /* use s->note_buf to store notes temporarily */
+    if (write_elf32_notes(buf_write_note, s) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    if (write_buffer(s->fd, s->flag_flatten, kh->offset_note, s->note_buf,
+                     s->note_size) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    /* get offset of dump_bitmap */
+    s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size) *
+                             dh->block_size;
+
+    /* get offset of page */
+    s->offset_page = (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size +
+                      dh->bitmap_blocks) * dh->block_size;
+
+out:
+    g_free(dh);
+    g_free(kh);
+    g_free(s->note_buf);
+
+    return ret;
+}
+
+/* write common header, sub header and elf note to vmcore */
+static int create_header64(DumpState *s)
+{
+    int ret = 0;
+    DiskDumpHeader64 *dh;
+    KdumpSubHeader64 *kh;
+    size_t size;
+
+    /* write common header, the version of kdump-compressed format is 5th */
+    size = sizeof(DiskDumpHeader64);
+    dh = g_malloc0(size);
+
+    strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
+    dh->header_version = 5;
+    dh->block_size = s->page_size;
+    dh->sub_hdr_size = sizeof(struct KdumpSubHeader64) + s->note_size;
+    dh->sub_hdr_size = divideup(dh->sub_hdr_size, dh->block_size);
+    dh->max_mapnr = s->max_mapnr;
+    dh->nr_cpus = s->nr_cpus;
+    dh->bitmap_blocks = divideup(s->len_dump_bitmap, s->page_size);
+    memcpy(&(dh->utsname.machine), "x86_64", 6);
+
+    if (write_buffer(s->fd, s->flag_flatten, 0, dh, size) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    /* write sub header */
+    size = sizeof(KdumpSubHeader64);
+    kh = g_malloc0(size);
+
+    kh->phys_base = PHYS_BASE;
+    kh->dump_level = DUMP_LEVEL;
+
+    kh->offset_note = DISKDUMP_HEADER_BLOCKS * dh->block_size + size;
+    kh->note_size = s->note_size;
+
+    if (write_buffer(s->fd, s->flag_flatten, dh->block_size, kh, size) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    /* write note */
+    s->note_buf = g_malloc0(s->note_size);
+    s->note_buf_offset = 0;
+
+    /* use s->note_buf to store notes temporarily */
+    if (write_elf64_notes(buf_write_note, s) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    if (write_buffer(s->fd, s->flag_flatten, kh->offset_note, s->note_buf,
+                     s->note_size) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    /* get offset of dump_bitmap */
+    s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size) *
+                             dh->block_size;
+
+    /* get offset of page */
+    s->offset_page = (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size +
+                      dh->bitmap_blocks) * dh->block_size;
+
+out:
+    g_free(dh);
+    g_free(kh);
+    g_free(s->note_buf);
+
+    return ret;
+}
+
+static int write_dump_header(DumpState *s)
+{
+    if (s->dump_info.d_machine == EM_386) {
+        return create_header32(s);
+    } else {
+        return create_header64(s);
+    }
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 81cbaa8..54ae4e5 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -20,6 +20,14 @@
 #define VERSION_FLAT_HEADER         (1)    /* version of flattened format */
 #define END_FLAG_FLAT_HEADER        (-1)
 
+#define KDUMP_SIGNATURE             "KDUMP   "
+#define SIG_LEN                     (sizeof(KDUMP_SIGNATURE) - 1)
+#define PHYS_BASE                   (0)
+#define DUMP_LEVEL                  (1)
+#define DISKDUMP_HEADER_BLOCKS      (1)
+
+#define divideup(x, y)              (((x) + ((y) - 1)) / (y))
+
 typedef struct ArchDumpInfo {
     int d_machine;  /* Architecture */
     int d_endian;   /* ELFDATA2LSB or ELFDATA2MSB */
@@ -37,6 +45,77 @@ typedef struct QEMU_PACKED MakedumpfileDataHeader {
     int64_t buf_size;
 } MakedumpfileDataHeader;
 
+typedef struct QEMU_PACKED NewUtsname {
+    char sysname[65];
+    char nodename[65];
+    char release[65];
+    char version[65];
+    char machine[65];
+    char domainname[65];
+} NewUtsname;
+
+typedef struct QEMU_PACKED DiskDumpHeader32 {
+    char signature[SIG_LEN];        /* = "KDUMP   " */
+    uint32_t header_version;        /* Dump header version */
+    NewUtsname utsname;             /* copy of system_utsname */
+    char timestamp[10];             /* Time stamp */
+    uint32_t status;                /* Above flags */
+    uint32_t block_size;            /* Size of a block in byte */
+    uint32_t sub_hdr_size;          /* Size of arch dependent header in block */
+    uint32_t bitmap_blocks;         /* Size of Memory bitmap in block */
+    uint32_t max_mapnr;             /* = max_mapnr */
+    uint32_t total_ram_blocks;      /* Number of blocks should be written */
+    uint32_t device_blocks;         /* Number of total blocks in dump device */
+    uint32_t written_blocks;        /* Number of written blocks */
+    uint32_t current_cpu;           /* CPU# which handles dump */
+    uint32_t nr_cpus;               /* Number of CPUs */
+} DiskDumpHeader32;
+
+typedef struct QEMU_PACKED DiskDumpHeader64 {
+    char signature[SIG_LEN];        /* = "KDUMP   " */
+    uint32_t header_version;        /* Dump header version */
+    NewUtsname utsname;             /* copy of system_utsname */
+    char timestamp[22];             /* Time stamp */
+    uint32_t status;                /* Above flags */
+    uint32_t block_size;            /* Size of a block in byte */
+    uint32_t sub_hdr_size;          /* Size of arch dependent header in block */
+    uint32_t bitmap_blocks;         /* Size of Memory bitmap in block */
+    uint32_t max_mapnr;             /* = max_mapnr */
+    uint32_t total_ram_blocks;      /* Number of blocks should be written */
+    uint32_t device_blocks;         /* Number of total blocks in dump device */
+    uint32_t written_blocks;        /* Number of written blocks */
+    uint32_t current_cpu;           /* CPU# which handles dump */
+    uint32_t nr_cpus;               /* Number of CPUs */
+} DiskDumpHeader64;
+
+typedef struct QEMU_PACKED KdumpSubHeader32 {
+    uint32_t phys_base;
+    uint32_t dump_level;            /* header_version 1 and later */
+    uint32_t split;                 /* header_version 2 and later */
+    uint32_t start_pfn;             /* header_version 2 and later */
+    uint32_t end_pfn;               /* header_version 2 and later */
+    uint64_t offset_vmcoreinfo;     /* header_version 3 and later */
+    uint32_t size_vmcoreinfo;       /* header_version 3 and later */
+    uint64_t offset_note;           /* header_version 4 and later */
+    uint32_t note_size;             /* header_version 4 and later */
+    uint64_t offset_eraseinfo;      /* header_version 5 and later */
+    uint32_t size_eraseinfo;        /* header_version 5 and later */
+} KdumpSubHeader32;
+
+typedef struct QEMU_PACKED KdumpSubHeader64 {
+    uint64_t phys_base;
+    uint32_t dump_level;            /* header_version 1 and later */
+    uint32_t split;                 /* header_version 2 and later */
+    uint64_t start_pfn;             /* header_version 2 and later */
+    uint64_t end_pfn;               /* header_version 2 and later */
+    uint64_t offset_vmcoreinfo;     /* header_version 3 and later */
+    uint64_t size_vmcoreinfo;       /* header_version 3 and later */
+    uint64_t offset_note;           /* header_version 4 and later */
+    uint64_t note_size;             /* header_version 4 and later */
+    uint64_t offset_eraseinfo;      /* header_version 5 and later */
+    uint64_t size_eraseinfo;        /* header_version 5 and later */
+} KdumpSubHeader64;
+
 int cpu_get_dump_info(ArchDumpInfo *info);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (4 preceding siblings ...)
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 5/9] dump: add API to write dump header Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-16  2:25   ` Stefan Hajnoczi
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 7/9] dump: Add APIs to operate DataCache Qiao Nuohan
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

functions are used to write 1st and 2nd dump_bitmap of kdump-compressed format,
which is used to indicate whether the corresponded page is existed in vmcore.
Dump level 1 is chosen, so 1st and 2nd dump_bitmap are same.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c                |  136 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/dump.h |    5 ++
 2 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/dump.c b/dump.c
index cb2f866..40a5ea5 100644
--- a/dump.c
+++ b/dump.c
@@ -79,12 +79,14 @@ typedef struct DumpState {
     bool flag_flatten;
     uint32_t nr_cpus;
     size_t page_size;
+    uint32_t page_shift;
     size_t max_mapnr;
     size_t len_dump_bitmap;
     void *note_buf;
     size_t note_buf_offset;
     off_t offset_dump_bitmap;
     off_t offset_page;
+    size_t num_dumpable;
 } DumpState;
 
 static int dump_cleanup(DumpState *s)
@@ -925,6 +927,140 @@ static int write_dump_header(DumpState *s)
     }
 }
 
+/* set dump_bitmap sequencely */
+static int set_dump_bitmap(int64_t last_pfn, int64_t pfn, uint32_t value,
+                           void *buf, DumpState *s)
+{
+    off_t old_offset, new_offset;
+    off_t offset_bitmap1, offset_bitmap2;
+    uint32_t byte, bit;
+
+    /* should not set the previous place */
+    if (last_pfn > pfn) {
+        return -1;
+    }
+
+    /*
+     * if the block needed to be set is not same as the one cached in buf, flush
+     * the cached buf to vmcore firstly
+     */
+    old_offset = BUFSIZE_BITMAP * (last_pfn / PFN_BUFBITMAP);
+    new_offset = BUFSIZE_BITMAP * (pfn / PFN_BUFBITMAP);
+
+    while (old_offset < new_offset) {
+        /* calculate the offset and write dump_bitmap */
+        offset_bitmap1 = s->offset_dump_bitmap + old_offset;
+        if (write_buffer(s->fd, s->flag_flatten, offset_bitmap1, buf,
+                         BUFSIZE_BITMAP) < 0) {
+            return -1;
+        }
+
+        /* dump level 1 is chosen, so 1st and 2nd bitmap are same */
+        offset_bitmap2 = s->offset_dump_bitmap + s->len_dump_bitmap / 2 +
+                         old_offset;
+        if (write_buffer(s->fd, s->flag_flatten, offset_bitmap2, buf,
+                         BUFSIZE_BITMAP) < 0) {
+            return -1;
+        }
+
+        memset(buf, 0, BUFSIZE_BITMAP);
+        old_offset += BUFSIZE_BITMAP;
+    }
+
+    /* get the exact place of the bit in the buf, and set it */
+    byte = (pfn % PFN_BUFBITMAP) >> 3;
+    bit = (pfn % PFN_BUFBITMAP) & 7;
+    if (value) {
+        ((char *)buf)[byte] |= 1<<bit;
+    } else {
+        ((char *)buf)[byte] &= ~(1<<bit);
+    }
+
+    return 0;
+}
+
+/* write the remaining dump_bitmap in buf to s->fd */
+static int sync_dump_bitmap(int64_t last_pfn, void *buf, DumpState *s)
+{
+    off_t last_offset, offset_bitmap1, offset_bitmap2;
+
+    /* nothing is stored in buf */
+    if (last_pfn < 0) {
+        return 0;
+    }
+
+    last_offset = BUFSIZE_BITMAP * (last_pfn / PFN_BUFBITMAP);
+
+    /* calculate the offset and write dump_bitmap */
+    offset_bitmap1 = s->offset_dump_bitmap + last_offset;
+    if (write_buffer(s->fd, s->flag_flatten, offset_bitmap1, buf,
+                     BUFSIZE_BITMAP) < 0) {
+        return -1;
+    }
+
+    offset_bitmap2 = s->offset_dump_bitmap + s->len_dump_bitmap / 2 +
+                     last_offset;
+    if (write_buffer(s->fd, s->flag_flatten, offset_bitmap2, buf,
+                     BUFSIZE_BITMAP) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_dump_bitmap(DumpState *s)
+{
+    int ret = 0;
+    int64_t pfn_start, pfn_end, pfn;
+    int64_t last_pfn;
+    void *dump_bitmap_buf;
+    size_t num_dumpable;
+    MemoryMapping *memory_mapping;
+
+    /* dump_bitmap_buf is used to store dump_bitmap temporarily */
+    dump_bitmap_buf = g_malloc0(BUFSIZE_BITMAP);
+
+    num_dumpable = 0;
+    last_pfn = -1;
+
+    /*
+     * exam memory page by page, and set the bit in dump_bitmap corresponded
+     * to the existing page
+     */
+    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+        pfn_start = paddr_to_pfn(memory_mapping->phys_addr, s->page_shift);
+        pfn_end = paddr_to_pfn(memory_mapping->phys_addr +
+                               memory_mapping->length, s->page_shift);
+
+        for (pfn = pfn_start; pfn < pfn_end; pfn++) {
+            ret = set_dump_bitmap(last_pfn, pfn, 1, dump_bitmap_buf, s);
+            if (ret < 0) {
+                dump_error(s, "dump: failed to set dump_bitmap.\n");
+                ret = -1;
+                goto out;
+            }
+
+            last_pfn = pfn;
+            num_dumpable++;
+        }
+    }
+
+    ret = sync_dump_bitmap(last_pfn, dump_bitmap_buf, s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to sync dump_bitmap.\n");
+        ret = -1;
+        goto out;
+    }
+
+    /* number of dumpable pages that will be dumped later */
+    s->num_dumpable = num_dumpable;
+
+out:
+    g_free(dump_bitmap_buf);
+
+    return ret;
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 54ae4e5..e67927d 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -25,8 +25,13 @@
 #define PHYS_BASE                   (0)
 #define DUMP_LEVEL                  (1)
 #define DISKDUMP_HEADER_BLOCKS      (1)
+#define BUFSIZE_BITMAP              (4096)
+#define PFN_BUFBITMAP               (CHAR_BIT * BUFSIZE_BITMAP)
+#define ARCH_PFN_OFFSET             (0)
 
 #define divideup(x, y)              (((x) + ((y) - 1)) / (y))
+#define paddr_to_pfn(X, page_shift) \
+    (((unsigned long long)(X) >> (page_shift)) - ARCH_PFN_OFFSET)
 
 typedef struct ArchDumpInfo {
     int d_machine;  /* Architecture */
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 7/9] dump: Add APIs to operate DataCache
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (5 preceding siblings ...)
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages Qiao Nuohan
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

DataCache is used to store data temporarily, then the data will be written to
vmcore. These functions will be called later when writing data of page to
vmcore.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c                |   52 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/dump.h |    9 ++++++++
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/dump.c b/dump.c
index 40a5ea5..9537f2d 100644
--- a/dump.c
+++ b/dump.c
@@ -1061,6 +1061,58 @@ out:
     return ret;
 }
 
+static void prepare_data_cache(DataCache *data_cache, DumpState *s)
+{
+    data_cache->fd = s->fd;
+    data_cache->data_size = 0;
+    data_cache->buf_size = BUFSIZE_DATA_CACHE;
+    data_cache->buf = g_malloc0(BUFSIZE_DATA_CACHE);
+}
+
+static int write_cache(DataCache *dc, bool flag_flatten, void *buf, size_t size)
+{
+    /*
+     * check if the space is enough to cache data, if not, write the cached
+     * data to dc->fd and reset the buf
+     */
+    if (dc->data_size + size > dc->buf_size) {
+        if (write_buffer(dc->fd, flag_flatten, dc->offset, dc->buf,
+                         dc->data_size) < 0) {
+            return -1;
+        }
+
+        dc->offset += dc->data_size;
+        dc->data_size = 0;
+    }
+
+    memcpy(dc->buf + dc->data_size, buf, size);
+    dc->data_size += size;
+
+    return 0;
+}
+
+/* write the remaining data in dc->buf to dc->fd */
+static int sync_data_cache(DataCache *dc, bool flag_flatten)
+{
+    if (dc->data_size == 0) {
+        return 0;
+    }
+
+    if (write_buffer(dc->fd, flag_flatten, dc->offset, dc->buf,
+                     dc->data_size) < 0) {
+        return -1;
+    }
+
+    dc->offset += dc->data_size;
+
+    return 0;
+}
+
+static void free_data_cache(DataCache *data_cache)
+{
+    g_free(data_cache->buf);
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index e67927d..9704b28 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -28,6 +28,7 @@
 #define BUFSIZE_BITMAP              (4096)
 #define PFN_BUFBITMAP               (CHAR_BIT * BUFSIZE_BITMAP)
 #define ARCH_PFN_OFFSET             (0)
+#define BUFSIZE_DATA_CACHE          (4096 * 4)
 
 #define divideup(x, y)              (((x) + ((y) - 1)) / (y))
 #define paddr_to_pfn(X, page_shift) \
@@ -121,6 +122,14 @@ typedef struct QEMU_PACKED KdumpSubHeader64 {
     uint64_t size_eraseinfo;        /* header_version 5 and later */
 } KdumpSubHeader64;
 
+typedef struct DataCache {
+    int fd;             /* fd of the file where to write the cached data */
+    char *buf;          /* buffer for cached data */
+    size_t buf_size;    /* size of the buf */
+    size_t data_size;   /* size of cached data in buf */
+    off_t offset;       /* offset of the file */
+} DataCache;
+
 int cpu_get_dump_info(ArchDumpInfo *info);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (6 preceding siblings ...)
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 7/9] dump: Add APIs to operate DataCache Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-16  2:43   ` Stefan Hajnoczi
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 9/9] dump: Make kdump-compressed format available for 'dump-guest-memory' Qiao Nuohan
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

functions are used to write page desc and page data to vmcore.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 configure             |   50 +++++++++
 dump.c                |  264 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/dump.h |   16 +++
 3 files changed, 330 insertions(+), 0 deletions(-)

diff --git a/configure b/configure
index 0e0adde..0927972 100755
--- a/configure
+++ b/configure
@@ -231,6 +231,8 @@ libusb=""
 usb_redir=""
 glx=""
 zlib="yes"
+lzo="no"
+snappy="no"
 guest_agent="yes"
 want_tools="yes"
 libiscsi=""
@@ -912,6 +914,10 @@ for opt do
   ;;
   --disable-zlib-test) zlib="no"
   ;;
+  --enable-lzo) lzo="yes"
+  ;;
+  --enable-snappy) snappy="yes"
+  ;;
   --enable-guest-agent) guest_agent="yes"
   ;;
   --disable-guest-agent) guest_agent="no"
@@ -1471,6 +1477,42 @@ fi
 libs_softmmu="$libs_softmmu -lz"
 
 ##########################################
+# lzo check
+
+if test "$lzo" != "no" ; then
+    cat > $TMPC << EOF
+#include <lzo/lzo1x.h>
+int main(void) { lzo_version(); return 0; }
+EOF
+    if compile_prog "" "-llzo2" ; then
+        :
+    else
+        error_exit "lzo check failed" \
+            "Make sure to have the lzo libs and headers installed."
+    fi
+
+    libs_softmmu="$libs_softmmu -llzo2"
+fi
+
+##########################################
+# snappy check
+
+if test "$snappy" != "no" ; then
+    cat > $TMPC << EOF
+#include <snappy-c.h>
+int main(void) { snappy_max_compressed_length(4096); return 0; }
+EOF
+    if compile_prog "" "-lsnappy" ; then
+        :
+    else
+        error_exit "snappy check failed" \
+            "Make sure to have the snappy libs and headers installed."
+    fi
+
+    libs_softmmu="$libs_softmmu -lsnappy"
+fi
+
+##########################################
 # libseccomp check
 
 if test "$seccomp" != "no" ; then
@@ -3872,6 +3914,14 @@ if test "$glx" = "yes" ; then
   echo "GLX_LIBS=$glx_libs" >> $config_host_mak
 fi
 
+if test "$lzo" = "yes" ; then
+  echo "CONFIG_LZO=y" >> $config_host_mak
+fi
+
+if test "$snappy" = "yes" ; then
+  echo "CONFIG_SNAPPY=y" >> $config_host_mak
+fi
+
 if test "$libiscsi" = "yes" ; then
   echo "CONFIG_LIBISCSI=y" >> $config_host_mak
 fi
diff --git a/dump.c b/dump.c
index 9537f2d..a28e162 100644
--- a/dump.c
+++ b/dump.c
@@ -25,6 +25,14 @@
 #include "qapi/error.h"
 #include "qmp-commands.h"
 
+#include <zlib.h>
+#ifdef CONFIG_LZO
+#include <lzo/lzo1x.h>
+#endif
+#ifdef CONFIG_SNAPPY
+#include <snappy-c.h>
+#endif
+
 static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
 {
     if (endian == ELFDATA2LSB) {
@@ -87,6 +95,7 @@ typedef struct DumpState {
     off_t offset_dump_bitmap;
     off_t offset_page;
     size_t num_dumpable;
+    uint32_t flag_compress;
 } DumpState;
 
 static int dump_cleanup(DumpState *s)
@@ -1113,6 +1122,261 @@ static void free_data_cache(DataCache *data_cache)
     g_free(data_cache->buf);
 }
 
+static size_t get_len_buf_out(size_t page_size, uint32_t flag_compress)
+{
+    size_t len_buf_out_zlib, len_buf_out_lzo, len_buf_out_snappy;
+    size_t len_buf_out;
+
+    /* init buf_out */
+    len_buf_out_zlib = len_buf_out_lzo = len_buf_out_snappy = 0;
+
+    /* buf size for zlib */
+    len_buf_out_zlib = compressBound(page_size);
+
+    /* buf size for lzo */
+#ifdef CONFIG_LZO
+    if (flag_compress & DUMP_DH_COMPRESSED_LZO) {
+        if (lzo_init() != LZO_E_OK) {
+            /* return 0 to indicate lzo is unavailable */
+            return 0;
+        }
+    }
+
+    len_buf_out_lzo = page_size + page_size / 16 + 64 + 3;
+#endif
+
+#ifdef CONFIG_SNAPPY
+    /* buf size for snappy */
+    len_buf_out_snappy = snappy_max_compressed_length(page_size);
+#endif
+
+    /* get the biggest that can store all kinds of compressed page */
+    len_buf_out = MAX(len_buf_out_zlib,
+                      MAX(len_buf_out_lzo, len_buf_out_snappy));
+
+    return len_buf_out;
+}
+
+/*
+ * search memory blocks to find the exact place of the specified page, then
+ * dump the page into buf. memory should be read page by page, or it may exceed
+ * the boundary and fail to read
+ */
+static int readmem(void *bufptr, ram_addr_t addr, size_t size, DumpState *s)
+{
+    RAMBlock *block;
+
+    block = s->block;
+
+    while (block) {
+        if ((addr >= block->offset) &&
+            (addr + size <= block->offset + block->length)) {
+            memcpy(bufptr, block->host + (addr - block->offset), size);
+            return 0;
+        } else {
+            block = QTAILQ_NEXT(block, next);
+        }
+    }
+
+    return -1;
+}
+
+/*
+ * check if the page is all 0
+ */
+static inline bool is_zero_page(unsigned char *buf, long page_size)
+{
+    size_t i;
+
+    for (i = 0; i < page_size; i++) {
+        if (buf[i]) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static int write_dump_pages(DumpState *s)
+{
+    int ret = 0;
+    DataCache page_desc, page_data;
+    size_t len_buf_out, size_out;
+    unsigned char *buf_out = NULL;
+    off_t offset_desc, offset_data;
+    PageDesc pd, pd_zero;
+    uint64_t pfn_start, pfn_end, pfn;
+    unsigned char buf[s->page_size];
+    MemoryMapping *memory_mapping;
+    bool zero_page;
+
+    prepare_data_cache(&page_desc, s);
+    prepare_data_cache(&page_data, s);
+
+    /* prepare buffer to store compressed data */
+    len_buf_out = get_len_buf_out(s->page_size, s->flag_compress);
+    if (len_buf_out == 0) {
+        dump_error(s, "dump: failed to get length of output buffer.\n");
+        goto out;
+    }
+
+#ifdef CONFIG_LZO
+    lzo_bytep wrkmem;
+
+    wrkmem = g_malloc(LZO1X_1_MEM_COMPRESS);
+#endif
+
+    buf_out = g_malloc(len_buf_out);
+
+    /* get offset of page_desc and page_data in dump file */
+    offset_desc = s->offset_page;
+    offset_data = offset_desc + sizeof(PageDesc) * s->num_dumpable;
+    page_desc.offset = offset_desc;
+    page_data.offset = offset_data;
+
+    /*
+     * init zero page's page_desc and page_data, because every zero page
+     * uses the same page_data
+     */
+    pd_zero.size = s->page_size;
+    pd_zero.flags = 0;
+    pd_zero.offset = offset_data;
+    pd_zero.page_flags = 0;
+    memset(buf, 0, pd_zero.size);
+    ret = write_cache(&page_data, s->flag_flatten, buf, pd_zero.size);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write page data(zero page).\n");
+        goto out;
+    }
+
+    offset_data += pd_zero.size;
+
+    /* dump memory to vmcore page by page */
+    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+        pfn_start = paddr_to_pfn(memory_mapping->phys_addr, s->page_shift);
+        pfn_end = paddr_to_pfn(memory_mapping->phys_addr +
+                               memory_mapping->length, s->page_shift);
+
+        for (pfn = pfn_start; pfn < pfn_end; pfn++) {
+            memset(buf, 0, s->page_size);
+            ret = readmem(buf, pfn_to_paddr(pfn, s->page_shift), s->page_size,
+                          s);
+            if (ret < 0) {
+                dump_error(s, "dump: failed to read memory.\n");
+                goto out;
+            }
+
+            /* check zero page */
+            zero_page = is_zero_page(buf, s->page_size);
+            if (zero_page) {
+                ret = write_cache(&page_desc, s->flag_flatten, &pd_zero,
+                                  sizeof(PageDesc));
+                if (ret < 0) {
+                    dump_error(s, "dump: failed to write page desc.\n");
+                    goto out;
+                }
+            } else {
+                /*
+                 * not zero page, then:
+                 * 1. compress the page
+                 * 2. write the compressed page into the cache of page_data
+                 * 3. get page desc of the compressed page and write it into the
+                 *    cache of page_desc
+                 */
+                size_out = len_buf_out;
+                if ((s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) &&
+                        (compress2(buf_out, &size_out, buf, s->page_size,
+                        Z_BEST_SPEED) == Z_OK) && (size_out < s->page_size)) {
+                    pd.flags = DUMP_DH_COMPRESSED_ZLIB;
+                    pd.size  = size_out;
+
+                    ret = write_cache(&page_data, s->flag_flatten, buf_out,
+                                      pd.size);
+                    if (ret < 0) {
+                        dump_error(s, "dump: failed to write page data.\n");
+                        goto out;
+                    }
+#ifdef CONFIG_LZO
+                } else if ((s->flag_compress & DUMP_DH_COMPRESSED_LZO) &&
+                        (lzo1x_1_compress(buf, s->page_size, buf_out,
+                        &size_out, wrkmem) == LZO_E_OK) &&
+                        (size_out < s->page_size)) {
+                    pd.flags = DUMP_DH_COMPRESSED_LZO;
+                    pd.size  = size_out;
+
+                    ret = write_cache(&page_data, s->flag_flatten, buf_out,
+                                      pd.size);
+                    if (ret < 0) {
+                        dump_error(s, "dump: failed to write page data.\n");
+                        goto out;
+                    }
+#endif
+#ifdef CONFIG_SNAPPY
+                } else if ((s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) &&
+                        (snappy_compress((char *)buf, s->page_size,
+                        (char *)buf_out, (size_t *)&size_out) == SNAPPY_OK) &&
+                        (size_out < s->page_size)) {
+                    pd.flags = DUMP_DH_COMPRESSED_SNAPPY;
+                    pd.size  = size_out;
+
+                    ret = write_cache(&page_data, s->flag_flatten, buf_out,
+                                      pd.size);
+                    if (ret < 0) {
+                        dump_error(s, "dump: failed to write page data.\n");
+                        goto out;
+                    }
+#endif
+                } else {
+                    pd.flags = 0;
+                    pd.size = s->page_size;
+
+                    ret = write_cache(&page_data, s->flag_flatten, buf,
+                                      pd.size);
+                    if (ret < 0) {
+                        dump_error(s, "dump: failed to write page data.\n");
+                        goto out;
+                    }
+                }
+
+                /* get and write page desc here */
+                pd.page_flags = 0;
+                pd.offset = offset_data;
+                offset_data += pd.size;
+
+                ret = write_cache(&page_desc, s->flag_flatten, &pd,
+                                  sizeof(PageDesc));
+                if (ret < 0) {
+                    dump_error(s, "dump: failed to write page desc.\n");
+                    goto out;
+                }
+            }
+        }
+    }
+
+    ret = sync_data_cache(&page_desc, s->flag_flatten);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to sync cache for page_desc.\n");
+        goto out;
+    }
+    ret = sync_data_cache(&page_data, s->flag_flatten);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to sync cache for page_data.\n");
+        goto out;
+    }
+
+out:
+    free_data_cache(&page_desc);
+    free_data_cache(&page_data);
+
+#ifdef CONFIG_LZO
+    g_free(wrkmem);
+#endif
+
+    g_free(buf_out);
+
+    return ret;
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 9704b28..c30fcc2 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -20,6 +20,13 @@
 #define VERSION_FLAT_HEADER         (1)    /* version of flattened format */
 #define END_FLAG_FLAT_HEADER        (-1)
 
+/*
+ * flag for compressed format
+ */
+#define DUMP_DH_COMPRESSED_ZLIB     (0x1)
+#define DUMP_DH_COMPRESSED_LZO      (0x2)
+#define DUMP_DH_COMPRESSED_SNAPPY   (0x4)
+
 #define KDUMP_SIGNATURE             "KDUMP   "
 #define SIG_LEN                     (sizeof(KDUMP_SIGNATURE) - 1)
 #define PHYS_BASE                   (0)
@@ -33,6 +40,8 @@
 #define divideup(x, y)              (((x) + ((y) - 1)) / (y))
 #define paddr_to_pfn(X, page_shift) \
     (((unsigned long long)(X) >> (page_shift)) - ARCH_PFN_OFFSET)
+#define pfn_to_paddr(X, page_shift) \
+    (((unsigned long long)(X) + ARCH_PFN_OFFSET) << (page_shift))
 
 typedef struct ArchDumpInfo {
     int d_machine;  /* Architecture */
@@ -130,6 +139,13 @@ typedef struct DataCache {
     off_t offset;       /* offset of the file */
 } DataCache;
 
+typedef struct PageDesc {
+    off_t offset;                   /* the offset of the page data*/
+    uint32_t size;                  /* the size of this dump page */
+    uint32_t flags;                 /* flags */
+    uint64_t page_flags;            /* page flags */
+} PageDesc;
+
 int cpu_get_dump_info(ArchDumpInfo *info);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH v5 9/9] dump: Make kdump-compressed format available for 'dump-guest-memory'
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (7 preceding siblings ...)
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages Qiao Nuohan
@ 2013-07-09  7:30 ` Qiao Nuohan
  2013-07-09  7:36 ` [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
  2013-12-13  2:07 ` Qiao Nuohan
  10 siblings, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:30 UTC (permalink / raw)
  To: stefanha, lcapitulino, afaerber, eblake
  Cc: anderson, Qiao Nuohan, kumagai-atsushi, zhangxh, qemu-devel

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
     it can be smaller than the ELF format because of the compression support.
  2. The kdump-compressed format is the 5th edition.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Signed-off-by: Zhang Xiaohe <zhangxh@cn.fujitsu.com>
---
 dump.c                |  154 ++++++++++++++++++++++++++++++++++++++++++++++---
 hmp-commands.hx       |   12 +++-
 hmp.c                 |   23 +++++++-
 include/sysemu/dump.h |    1 +
 qapi-schema.json      |   22 +++++++-
 qmp-commands.hx       |    6 +-
 6 files changed, 201 insertions(+), 17 deletions(-)

diff --git a/dump.c b/dump.c
index a28e162..a78ac8d 100644
--- a/dump.c
+++ b/dump.c
@@ -1377,6 +1377,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)
 {
     RAMBlock *block;
@@ -1405,7 +1469,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)
 {
     CPUArchState *env;
@@ -1470,6 +1554,44 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
         qemu_get_guest_simple_memory_mapping(&s->list);
     }
 
+    /* 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 to avoid seek
+         */
+        s->flag_flatten = use_flatten_format(fd);
+
+        s->nr_cpus = nr_cpus;
+        s->page_size = PAGE_SIZE;
+        s->page_shift = ffs(s->page_size) - 1;
+
+        get_max_mapnr(s);
+
+        size_t tmp;
+        tmp = divideup(divideup(s->max_mapnr, CHAR_BIT), s->page_size);
+        s->len_dump_bitmap = tmp * s->page_size * 2;
+
+        return 0;
+    }
+
     if (s->has_filter) {
         memory_mapping_filter(&s->list, s->begin, s->length);
     }
@@ -1527,8 +1649,9 @@ cleanup:
 }
 
 void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
-                           int64_t begin, bool has_length, int64_t length,
-                           Error **errp)
+                           int64_t begin, bool has_length,
+                           int64_t length, bool has_format,
+                           DumpGuestMemoryFormat format, Error **errp)
 {
     const char *p;
     int fd = -1;
@@ -1543,6 +1666,12 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
         error_set(errp, QERR_MISSING_PARAMETER, "begin");
         return;
     }
+    /* kdump-compressed format doesn't support paging or filter */
+    if ((has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) &&
+        (paging || has_begin || has_length)) {
+        error_set(errp, QERR_INVALID_PARAMETER_COMBINATION);
+        return;
+    }
 
 #if !defined(WIN32)
     if (strstart(file, "fd:", &p)) {
@@ -1566,17 +1695,24 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
         return;
     }
 
-    s = g_malloc(sizeof(DumpState));
+    s = g_malloc0(sizeof(DumpState));
 
-    ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
+    ret = dump_init(s, fd, has_format, format, paging, has_begin,
+                    begin, length, errp);
     if (ret < 0) {
-        g_free(s);
-        return;
+        goto out;
     }
 
-    if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
-        error_set(errp, QERR_IO_ERROR);
+    if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
+        if (create_kdump_vmcore(s) < 0 && !error_is_set(s->errp)) {
+            error_set(errp, QERR_IO_ERROR);
+        }
+    } else {
+        if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
+            error_set(errp, QERR_IO_ERROR);
+        }
     }
 
+out:
     g_free(s);
 }
diff --git a/hmp-commands.hx b/hmp-commands.hx
index d1cdcfb..7b99912 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -993,17 +993,19 @@ ETEXI
 
     {
         .name       = "dump-guest-memory",
-        .args_type  = "paging:-p,filename:F,begin:i?,length:i?",
-        .params     = "[-p] filename [begin] [length]",
+        .args_type  = "paging:-p,filename:F,begin:i?,length:i?,format:s?",
+        .params     = "[-p] filename [begin] [length] [format]",
         .help       = "dump guest memory to file"
                       "\n\t\t\t begin(optional): the starting physical address"
-                      "\n\t\t\t length(optional): the memory size, in bytes",
+                      "\n\t\t\t length(optional): the memory size, in bytes"
+                      "\n\t\t\t format(optional): the format of guest memory dump,"
+                      "\n\t\t\t it can be elf|kdump-zlib|kdump-lzo|kdump-snappy",
         .mhandler.cmd = hmp_dump_guest_memory,
     },
 
 
 STEXI
-@item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length}
+@item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length} @var{format}
 @findex dump-guest-memory
 Dump guest memory to @var{protocol}. The file can be processed with crash or
 gdb.
@@ -1013,6 +1015,8 @@ gdb.
             specified with length together.
     length: the memory size, in bytes. It's optional, and should be specified
             with begin together.
+    format: the format of guest memory dump. It's optional, and can be
+            elf|kdump-zlib|kdump-lzo|kdump-snappy
 ETEXI
 
     {
diff --git a/hmp.c b/hmp.c
index 2daed43..4204866 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1225,9 +1225,12 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
     const char *file = qdict_get_str(qdict, "filename");
     bool has_begin = qdict_haskey(qdict, "begin");
     bool has_length = qdict_haskey(qdict, "length");
+    bool has_format = qdict_haskey(qdict, "format");
     int64_t begin = 0;
     int64_t length = 0;
+    const char *format = NULL;
     char *prot;
+    enum DumpGuestMemoryFormat dump_format;
 
     if (has_begin) {
         begin = qdict_get_int(qdict, "begin");
@@ -1235,11 +1238,29 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
     if (has_length) {
         length = qdict_get_int(qdict, "length");
     }
+    if (has_format) {
+        format = qdict_get_str(qdict, "format");
+    }
+
+    if (strcmp(format, "elf") == 0) {
+        dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
+    } else if (strcmp(format, "kdump-zlib") == 0) {
+        dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
+    } else if (strcmp(format, "kdump-lzo") == 0) {
+        dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO;
+    } else if (strcmp(format, "kdump-snappy") == 0) {
+        dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
+    } else {
+        error_set(&errp, QERR_INVALID_PARAMETER_VALUE,
+                  "format", "elf|kdump-zlib|kdump-lzo|kdump-snappy");
+        hmp_handle_error(mon, &errp);
+        return;
+    }
 
     prot = g_strconcat("file:", file, NULL);
 
     qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
-                          &errp);
+                          has_format, dump_format, &errp);
     hmp_handle_error(mon, &errp);
     g_free(prot);
 }
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index c30fcc2..06fc33e 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -27,6 +27,7 @@
 #define DUMP_DH_COMPRESSED_LZO      (0x2)
 #define DUMP_DH_COMPRESSED_SNAPPY   (0x4)
 
+#define PAGE_SIZE                   (4096)
 #define KDUMP_SIGNATURE             "KDUMP   "
 #define SIG_LEN                     (sizeof(KDUMP_SIGNATURE) - 1)
 #define PHYS_BASE                   (0)
diff --git a/qapi-schema.json b/qapi-schema.json
index 5c32528..181bd20 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2489,6 +2489,24 @@
 { 'command': 'device_del', 'data': {'id': 'str'} }
 
 ##
+# @DumpGuestMemoryFormat:
+#
+# An enumeration of guest-memory-dump's format.
+#
+# @elf: elf format
+#
+# @kdump-zlib: kdump-compressed format with zlib-compressed
+#
+# @kdump-lzo: kdump-compressed format with zlib-compressed
+#
+# @kdump-snappy: kdump-compressed format with zlib-compressed
+#
+# Since: 1.6
+##
+{ 'enum': 'DumpGuestMemoryFormat',
+  'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy' ] }
+
+##
 # @dump-guest-memory
 #
 # Dump guest's memory to vmcore. It is a synchronous operation that can take
@@ -2524,13 +2542,15 @@
 #          want to dump all guest's memory, please specify the start @begin
 #          and @length
 #
+# @format: #optional if specified, the format of guest memory dump. (since 1.6)
+#
 # Returns: nothing on success
 #
 # Since: 1.2
 ##
 { 'command': 'dump-guest-memory',
   'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
-            '*length': 'int' } }
+            '*length': 'int', '*format': 'DumpGuestMemoryFormat' } }
 
 ##
 # @netdev_add:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 362f0e1..a58f0ae 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -788,8 +788,8 @@ EQMP
 
     {
         .name       = "dump-guest-memory",
-        .args_type  = "paging:b,protocol:s,begin:i?,end:i?",
-        .params     = "-p protocol [begin] [length]",
+        .args_type  = "paging:b,protocol:s,begin:i?,length:i?,format:s?",
+        .params     = "-p protocol [begin] [length] [format]",
         .help       = "dump guest memory to file",
         .user_print = monitor_user_noop,
         .mhandler.cmd_new = qmp_marshal_input_dump_guest_memory,
@@ -810,6 +810,8 @@ Arguments:
            with length together (json-int)
 - "length": the memory size, in bytes. It's optional, and should be specified
             with begin together (json-int)
+- "format": the format of guest memory dump. It's optional, and can be
+            elf|kdump-zlib|kdump-lzo|kdump-snappy (json-string)
 
 Example:
 
-- 
1.7.1

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (8 preceding siblings ...)
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 9/9] dump: Make kdump-compressed format available for 'dump-guest-memory' Qiao Nuohan
@ 2013-07-09  7:36 ` Qiao Nuohan
  2013-07-15  9:56   ` Qiao Nuohan
  2013-07-31  9:26   ` Qiao Nuohan
  2013-12-13  2:07 ` Qiao Nuohan
  10 siblings, 2 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-09  7:36 UTC (permalink / raw)
  To: Qiao Nuohan
  Cc: stefanha, qemu-devel, lcapitulino, zhangxh, anderson,
	kumagai-atsushi, afaerber

On 07/09/2013 03:30 PM, Qiao Nuohan wrote:
> The last version is here:
> http://lists.gnu.org/archive/html/qemu-devel/2013-05/msg03866.html

Hi all,

Still waiting for introspection... And comments about format will be very
helpful.

Thanks!

--
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-09  7:36 ` [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
@ 2013-07-15  9:56   ` Qiao Nuohan
  2013-07-16  2:45     ` Stefan Hajnoczi
  2013-07-31  9:26   ` Qiao Nuohan
  1 sibling, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-15  9:56 UTC (permalink / raw)
  To: stefanha, qemu-devel
  Cc: lcapitulino, Qiao Nuohan, zhangxh, anderson, kumagai-atsushi, afaerber

On 07/09/2013 03:36 PM, Qiao Nuohan wrote:
> Still waiting for introspection... And comments about format will be very
> helpful.

Hi Stefan and others,

What do you think about the process of creating vmcore in kdump-compressed
format?

-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 2/9] dump: Add API to write header of flatten format
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 2/9] dump: Add API to write header of flatten format Qiao Nuohan
@ 2013-07-16  2:06   ` Stefan Hajnoczi
  2013-07-16  3:50     ` Qiao Nuohan
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan Hajnoczi @ 2013-07-16  2:06 UTC (permalink / raw)
  To: Qiao Nuohan
  Cc: qemu-devel, lcapitulino, zhangxh, anderson, kumagai-atsushi, afaerber

On Tue, Jul 09, 2013 at 03:30:07PM +0800, Qiao Nuohan wrote:
> +static int write_start_flat_header(int fd)
> +{
> +    char buf[MAX_SIZE_MDF_HEADER];
> +    MakedumpfileHeader mh;

Why is buf[] necessary?  You can write mh directly.

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

* Re: [Qemu-devel] [PATCH v5 5/9] dump: add API to write dump header
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 5/9] dump: add API to write dump header Qiao Nuohan
@ 2013-07-16  2:18   ` Stefan Hajnoczi
  0 siblings, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2013-07-16  2:18 UTC (permalink / raw)
  To: Qiao Nuohan
  Cc: qemu-devel, lcapitulino, zhangxh, anderson, kumagai-atsushi, afaerber

On Tue, Jul 09, 2013 at 03:30:10PM +0800, Qiao Nuohan wrote:
> +/* write common header, sub header and elf note to vmcore */
> +static int create_header32(DumpState *s)
> +{
> +    int ret = 0;
> +    DiskDumpHeader32 *dh;
> +    KdumpSubHeader32 *kh;
> +    size_t size;
> +
> +    /* write common header, the version of kdump-compressed format is 5th */
> +    size = sizeof(DiskDumpHeader32);
> +    dh = g_malloc0(size);
> +
> +    strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
> +    dh->header_version = 5;
> +    dh->block_size = s->page_size;
> +    dh->sub_hdr_size = sizeof(struct KdumpSubHeader32) + s->note_size;
> +    dh->sub_hdr_size = divideup(dh->sub_hdr_size, dh->block_size);
> +    dh->max_mapnr = s->max_mapnr;
> +    dh->nr_cpus = s->nr_cpus;
> +    dh->bitmap_blocks = divideup(s->len_dump_bitmap, s->page_size);
> +    memcpy(&(dh->utsname.machine), "i686", 4);
> +
> +    if (write_buffer(s->fd, s->flag_flatten, 0, dh, size) < 0) {
> +        ret = -1;
> +        goto out;
> +    }
> +
> +    /* write sub header */
> +    size = sizeof(KdumpSubHeader32);
> +    kh = g_malloc0(size);
> +
> +    kh->phys_base = PHYS_BASE;
> +    kh->dump_level = DUMP_LEVEL;
> +
> +    kh->offset_note = DISKDUMP_HEADER_BLOCKS * dh->block_size + size;
> +    kh->note_size = s->note_size;
> +
> +    if (write_buffer(s->fd, s->flag_flatten, dh->block_size, kh, size) < 0) {
> +        ret = -1;
> +        goto out;
> +    }
> +
> +    /* write note */
> +    s->note_buf = g_malloc(s->note_size);
> +    s->note_buf_offset = 0;
> +
> +    /* use s->note_buf to store notes temporarily */
> +    if (write_elf32_notes(buf_write_note, s) < 0) {
> +        ret = -1;
> +        goto out;
> +    }
> +
> +    if (write_buffer(s->fd, s->flag_flatten, kh->offset_note, s->note_buf,
> +                     s->note_size) < 0) {
> +        ret = -1;
> +        goto out;
> +    }
> +
> +    /* get offset of dump_bitmap */
> +    s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size) *
> +                             dh->block_size;
> +
> +    /* get offset of page */
> +    s->offset_page = (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size +
> +                      dh->bitmap_blocks) * dh->block_size;
> +
> +out:
> +    g_free(dh);
> +    g_free(kh);
> +    g_free(s->note_buf);

These variables must be initialized to NULL so that an early goto out
does not access uninitialized memory.

> +
> +    return ret;
> +}
> +
> +/* write common header, sub header and elf note to vmcore */
> +static int create_header64(DumpState *s)
> +{
> +    int ret = 0;
> +    DiskDumpHeader64 *dh;
> +    KdumpSubHeader64 *kh;

Same here.

> diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
> index 81cbaa8..54ae4e5 100644
> --- a/include/sysemu/dump.h
> +++ b/include/sysemu/dump.h
> @@ -20,6 +20,14 @@
>  #define VERSION_FLAT_HEADER         (1)    /* version of flattened format */
>  #define END_FLAG_FLAT_HEADER        (-1)
>  
> +#define KDUMP_SIGNATURE             "KDUMP   "
> +#define SIG_LEN                     (sizeof(KDUMP_SIGNATURE) - 1)
> +#define PHYS_BASE                   (0)
> +#define DUMP_LEVEL                  (1)
> +#define DISKDUMP_HEADER_BLOCKS      (1)
> +
> +#define divideup(x, y)              (((x) + ((y) - 1)) / (y))

Please use QEMU's DIV_ROUND_UP().

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

* Re: [Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap Qiao Nuohan
@ 2013-07-16  2:25   ` Stefan Hajnoczi
  0 siblings, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2013-07-16  2:25 UTC (permalink / raw)
  To: Qiao Nuohan
  Cc: qemu-devel, lcapitulino, zhangxh, anderson, kumagai-atsushi, afaerber

On Tue, Jul 09, 2013 at 03:30:11PM +0800, Qiao Nuohan wrote:
> +/* set dump_bitmap sequencely */
> +static int set_dump_bitmap(int64_t last_pfn, int64_t pfn, uint32_t value,
> +                           void *buf, DumpState *s)
> +{
> +    off_t old_offset, new_offset;
> +    off_t offset_bitmap1, offset_bitmap2;
> +    uint32_t byte, bit;
> +
> +    /* should not set the previous place */
> +    if (last_pfn > pfn) {
> +        return -1;
> +    }
> +
> +    /*
> +     * if the block needed to be set is not same as the one cached in buf, flush
> +     * the cached buf to vmcore firstly
> +     */
> +    old_offset = BUFSIZE_BITMAP * (last_pfn / PFN_BUFBITMAP);
> +    new_offset = BUFSIZE_BITMAP * (pfn / PFN_BUFBITMAP);
> +
> +    while (old_offset < new_offset) {
> +        /* calculate the offset and write dump_bitmap */
> +        offset_bitmap1 = s->offset_dump_bitmap + old_offset;
> +        if (write_buffer(s->fd, s->flag_flatten, offset_bitmap1, buf,
> +                         BUFSIZE_BITMAP) < 0) {
> +            return -1;
> +        }
> +
> +        /* dump level 1 is chosen, so 1st and 2nd bitmap are same */
> +        offset_bitmap2 = s->offset_dump_bitmap + s->len_dump_bitmap / 2 +
> +                         old_offset;
> +        if (write_buffer(s->fd, s->flag_flatten, offset_bitmap2, buf,
> +                         BUFSIZE_BITMAP) < 0) {
> +            return -1;
> +        }

Can you reuse sync_dump_bitmap() here instead of duplicating this code?

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

* Re: [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages
  2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages Qiao Nuohan
@ 2013-07-16  2:43   ` Stefan Hajnoczi
  2013-07-16  3:40     ` Qiao Nuohan
  2013-07-16 16:28     ` Eric Blake
  0 siblings, 2 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2013-07-16  2:43 UTC (permalink / raw)
  To: Qiao Nuohan
  Cc: qemu-devel, lcapitulino, zhangxh, anderson, kumagai-atsushi, afaerber

On Tue, Jul 09, 2013 at 03:30:13PM +0800, Qiao Nuohan wrote:
>  if test "$seccomp" != "no" ; then
> @@ -3872,6 +3914,14 @@ if test "$glx" = "yes" ; then
>    echo "GLX_LIBS=$glx_libs" >> $config_host_mak
>  fi
>  
> +if test "$lzo" = "yes" ; then
> +  echo "CONFIG_LZO=y" >> $config_host_mak
> +fi
> +
> +if test "$snappy" = "yes" ; then
> +  echo "CONFIG_SNAPPY=y" >> $config_host_mak
> +fi

Please also include a run-time check so QEMU can produce an error when a
user chooses a compression algorithm which is not built in.  For
example, the user should get a clear error when they select Snappy but
QEMU was built without Snappy support.

> +static size_t get_len_buf_out(size_t page_size, uint32_t flag_compress)
> +{
> +    size_t len_buf_out_zlib, len_buf_out_lzo, len_buf_out_snappy;
> +    size_t len_buf_out;
> +
> +    /* init buf_out */
> +    len_buf_out_zlib = len_buf_out_lzo = len_buf_out_snappy = 0;
> +
> +    /* buf size for zlib */
> +    len_buf_out_zlib = compressBound(page_size);
> +
> +    /* buf size for lzo */
> +#ifdef CONFIG_LZO
> +    if (flag_compress & DUMP_DH_COMPRESSED_LZO) {
> +        if (lzo_init() != LZO_E_OK) {
> +            /* return 0 to indicate lzo is unavailable */
> +            return 0;
> +        }
> +    }
> +
> +    len_buf_out_lzo = page_size + page_size / 16 + 64 + 3;

Please introduce constants for these magic numbers.  I don't know what
they mean.

> +/*
> + * check if the page is all 0
> + */
> +static inline bool is_zero_page(unsigned char *buf, long page_size)

QEMU has an optimized buffer_is_zero() function which you can use
instead.

> +
> +static int write_dump_pages(DumpState *s)
> +{
> +    int ret = 0;
> +    DataCache page_desc, page_data;
> +    size_t len_buf_out, size_out;
> +    unsigned char *buf_out = NULL;
> +    off_t offset_desc, offset_data;
> +    PageDesc pd, pd_zero;
> +    uint64_t pfn_start, pfn_end, pfn;
> +    unsigned char buf[s->page_size];
> +    MemoryMapping *memory_mapping;
> +    bool zero_page;
> +
> +    prepare_data_cache(&page_desc, s);
> +    prepare_data_cache(&page_data, s);
> +
> +    /* prepare buffer to store compressed data */
> +    len_buf_out = get_len_buf_out(s->page_size, s->flag_compress);
> +    if (len_buf_out == 0) {
> +        dump_error(s, "dump: failed to get length of output buffer.\n");
> +        goto out;

This goto jumps over the declaration of wrkmem.  The g_free(wrkmem)
below will result in undefined behavior!  Please define wrkmem above and
initialize it to NULL.

> @@ -130,6 +139,13 @@ typedef struct DataCache {
>      off_t offset;       /* offset of the file */
>  } DataCache;
>  
> +typedef struct PageDesc {
> +    off_t offset;                   /* the offset of the page data*/

The guest may be 32-bit or 64-bit, independently of the QEMU host
wordsize.  Is off_t correct when running a 64-bit guest on a 32-bit
host?

I guess you are assuming off_t == uint64_t here?

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-15  9:56   ` Qiao Nuohan
@ 2013-07-16  2:45     ` Stefan Hajnoczi
  0 siblings, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2013-07-16  2:45 UTC (permalink / raw)
  To: Qiao Nuohan
  Cc: qemu-devel, lcapitulino, zhangxh, anderson, kumagai-atsushi, afaerber

On Mon, Jul 15, 2013 at 05:56:31PM +0800, Qiao Nuohan wrote:
> On 07/09/2013 03:36 PM, Qiao Nuohan wrote:
> >Still waiting for introspection... And comments about format will be very
> >helpful.
> 
> Hi Stefan and others,
> 
> What do you think about the process of creating vmcore in kdump-compressed
> format?

Sorry, I was on vacation last week.

Stefan

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

* Re: [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages
  2013-07-16  2:43   ` Stefan Hajnoczi
@ 2013-07-16  3:40     ` Qiao Nuohan
  2013-07-16 16:28     ` Eric Blake
  1 sibling, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-16  3:40 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, lcapitulino, zhangxh, anderson, kumagai-atsushi, afaerber

Thanks for your comments!


On 07/16/2013 10:43 AM, Stefan Hajnoczi wrote:
>> @@ -130,6 +139,13 @@ typedef struct DataCache {
>> >        off_t offset;       /* offset of the file */
>> >    } DataCache;
>> >
>> >  +typedef struct PageDesc {
>> >  +    off_t offset;                   /* the offset of the page data*/
> The guest may be 32-bit or 64-bit, independently of the QEMU host
> wordsize.  Is off_t correct when running a 64-bit guest on a 32-bit
> host?
>
> I guess you are assuming off_t == uint64_t here?
>

The 'offset' should be 64-bit in kdump format both on 32-bit and 64-bit. And I
will avoid using off_t in structure used by kdump format. Thanks for pointing
it out.

-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 2/9] dump: Add API to write header of flatten format
  2013-07-16  2:06   ` Stefan Hajnoczi
@ 2013-07-16  3:50     ` Qiao Nuohan
  0 siblings, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-16  3:50 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, lcapitulino, zhangxh, anderson, kumagai-atsushi, afaerber

On 07/16/2013 10:06 AM, Stefan Hajnoczi wrote:
> On Tue, Jul 09, 2013 at 03:30:07PM +0800, Qiao Nuohan wrote:
>> +static int write_start_flat_header(int fd)
>> +{
>> +    char buf[MAX_SIZE_MDF_HEADER];
>> +    MakedumpfileHeader mh;
>
> Why is buf[] necessary?  You can write mh directly.
>

The size of header should be MAX_SIZE_MDF_HEADER not "sizeof(mh)". So the buf[]
is used to fill the gap between mh and the first MakedumpfileDataHeader.

-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages
  2013-07-16  2:43   ` Stefan Hajnoczi
  2013-07-16  3:40     ` Qiao Nuohan
@ 2013-07-16 16:28     ` Eric Blake
  1 sibling, 0 replies; 29+ messages in thread
From: Eric Blake @ 2013-07-16 16:28 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, lcapitulino, Qiao Nuohan, anderson, zhangxh,
	kumagai-atsushi, afaerber

[-- Attachment #1: Type: text/plain, Size: 1076 bytes --]

On 07/15/2013 08:43 PM, Stefan Hajnoczi wrote:
> On Tue, Jul 09, 2013 at 03:30:13PM +0800, Qiao Nuohan wrote:
>>  if test "$seccomp" != "no" ; then
>> @@ -3872,6 +3914,14 @@ if test "$glx" = "yes" ; then
>>    echo "GLX_LIBS=$glx_libs" >> $config_host_mak
>>  fi
>>  
>> +if test "$lzo" = "yes" ; then
>> +  echo "CONFIG_LZO=y" >> $config_host_mak
>> +fi
>> +
>> +if test "$snappy" = "yes" ; then
>> +  echo "CONFIG_SNAPPY=y" >> $config_host_mak
>> +fi
> 
> Please also include a run-time check so QEMU can produce an error when a
> user chooses a compression algorithm which is not built in.  For
> example, the user should get a clear error when they select Snappy but
> QEMU was built without Snappy support.

Here's an instance where runtime introspection would come in handy -
knowing which values of an enum are actually supportable, vs. the entire
list of names but relying on decent errors for the elements that weren't
compiled in.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-09  7:36 ` [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
  2013-07-15  9:56   ` Qiao Nuohan
@ 2013-07-31  9:26   ` Qiao Nuohan
  2013-07-31 12:23     ` Laszlo Ersek
  1 sibling, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-07-31  9:26 UTC (permalink / raw)
  To: lcapitulino, Amos; +Cc: stefanha, Qiao Nuohan, qemu-devel

Hello Luiz and Amos,

My patches are waiting for introspection. But now I cannot quite catch the 
situation of introspection, so I hope to get some information about current 
state from you. It will be very appreciated.


On 07/09/2013 03:36 PM, Qiao Nuohan wrote:
> On 07/09/2013 03:30 PM, Qiao Nuohan wrote:
>> The last version is here:
>> http://lists.gnu.org/archive/html/qemu-devel/2013-05/msg03866.html
>
> Hi all,
>
> Still waiting for introspection... And comments about format will be very
> helpful.
>
> Thanks!
>


-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-31  9:26   ` Qiao Nuohan
@ 2013-07-31 12:23     ` Laszlo Ersek
  2013-07-31 13:10       ` Luiz Capitulino
  2013-08-02  3:37       ` Qiao Nuohan
  0 siblings, 2 replies; 29+ messages in thread
From: Laszlo Ersek @ 2013-07-31 12:23 UTC (permalink / raw)
  To: Qiao Nuohan; +Cc: stefanha, Amos, qemu-devel, lcapitulino

Hi Qiao,

On 07/31/13 11:26, Qiao Nuohan wrote:
> Hello Luiz and Amos,
> 
> My patches are waiting for introspection. But now I cannot quite catch
> the situation of introspection, so I hope to get some information about
> current state from you. It will be very appreciated.

I wasn't aware that you've been working on dump changes.

I'm afraid this series of yours, and my series

  [Qemu-devel] [PATCH 0/4] dump-guest-memory: correct the vmcores
  http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg05469.html

are going to conflict violently.

Since my series is a bugfix for existing, non-compressed functionality
(--> vmcores dumped for 3.5G+ guests are corrupt), *and* you look like a
vmcore/dump expert, could you please give it a look? :)

Normally, your series *should* take priority, because it's been on the
list for much longer. However considering the 1.6 hard freeze, my
series, being a bugfix, might go in earlier. Do you think you could
rebase your work on mine (if it is accepted, that is)?

Apologies for the mess...

Thanks
Laszlo

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-31 12:23     ` Laszlo Ersek
@ 2013-07-31 13:10       ` Luiz Capitulino
  2013-08-02  3:25         ` Qiao Nuohan
  2013-08-02  3:37       ` Qiao Nuohan
  1 sibling, 1 reply; 29+ messages in thread
From: Luiz Capitulino @ 2013-07-31 13:10 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: stefanha, Qiao Nuohan, Amos, qemu-devel

On Wed, 31 Jul 2013 14:23:08 +0200
Laszlo Ersek <lersek@redhat.com> wrote:

> Hi Qiao,
> 
> On 07/31/13 11:26, Qiao Nuohan wrote:
> > Hello Luiz and Amos,
> > 
> > My patches are waiting for introspection. But now I cannot quite catch
> > the situation of introspection, so I hope to get some information about
> > current state from you. It will be very appreciated.

QMP introspection didn't make it for 1.6. I'd say it's the same for this
series at this point in time, unless you have a compelling reason to
include this (but then you'd have to add this as a new command).

> I wasn't aware that you've been working on dump changes.
> 
> I'm afraid this series of yours, and my series
> 
>   [Qemu-devel] [PATCH 0/4] dump-guest-memory: correct the vmcores
>   http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg05469.html
> 
> are going to conflict violently.
> 
> Since my series is a bugfix for existing, non-compressed functionality
> (--> vmcores dumped for 3.5G+ guests are corrupt), *and* you look like a
> vmcore/dump expert, could you please give it a look? :)
> 
> Normally, your series *should* take priority, because it's been on the
> list for much longer. However considering the 1.6 hard freeze, my
> series, being a bugfix, might go in earlier. Do you think you could
> rebase your work on mine (if it is accepted, that is)?

That's my thinking too.

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-31 13:10       ` Luiz Capitulino
@ 2013-08-02  3:25         ` Qiao Nuohan
  2013-08-02  3:41           ` Amos Kong
  0 siblings, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-08-02  3:25 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: stefanha, Amos, Laszlo Ersek, qemu-devel

On 07/31/2013 09:10 PM, Luiz Capitulino wrote:
> QMP introspection didn't make it for 1.6.

Thanks for your info. I will still wait for introspection.

-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-31 12:23     ` Laszlo Ersek
  2013-07-31 13:10       ` Luiz Capitulino
@ 2013-08-02  3:37       ` Qiao Nuohan
  1 sibling, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-08-02  3:37 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: stefanha, Amos, qemu-devel, lcapitulino

On 07/31/2013 08:23 PM, Laszlo Ersek wrote:

>
> Since my series is a bugfix for existing, non-compressed functionality
> (-->  vmcores dumped for 3.5G+ guests are corrupt), *and* you look like a
> vmcore/dump expert, could you please give it a look? :)

I see.

>
> Normally, your series *should* take priority, because it's been on the
> list for much longer. However considering the 1.6 hard freeze, my
> series, being a bugfix, might go in earlier. Do you think you could
> rebase your work on mine (if it is accepted, that is)?
>
> Apologies for the mess...
>

Never mind about your mess, for I am still waiting for introspection. And your
patches seem good to me.


-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-08-02  3:25         ` Qiao Nuohan
@ 2013-08-02  3:41           ` Amos Kong
  2013-08-02  3:43             ` Qiao Nuohan
  0 siblings, 1 reply; 29+ messages in thread
From: Amos Kong @ 2013-08-02  3:41 UTC (permalink / raw)
  To: Qiao Nuohan; +Cc: stefanha, Laszlo Ersek, qemu-devel, Luiz Capitulino

On Fri, Aug 02, 2013 at 11:25:17AM +0800, Qiao Nuohan wrote:
> On 07/31/2013 09:10 PM, Luiz Capitulino wrote:
> >QMP introspection didn't make it for 1.6.
> 
> Thanks for your info. I will still wait for introspection.
 
Can you help to review if the output of my patch v2 is ok for you?

> -- 
> Regards
> Qiao Nuohan

-- 
			Amos.

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-08-02  3:41           ` Amos Kong
@ 2013-08-02  3:43             ` Qiao Nuohan
  0 siblings, 0 replies; 29+ messages in thread
From: Qiao Nuohan @ 2013-08-02  3:43 UTC (permalink / raw)
  To: Amos Kong; +Cc: stefanha, Laszlo Ersek, qemu-devel, Luiz Capitulino

On 08/02/2013 11:41 AM, Amos Kong wrote:
> On Fri, Aug 02, 2013 at 11:25:17AM +0800, Qiao Nuohan wrote:
>> On 07/31/2013 09:10 PM, Luiz Capitulino wrote:
>>> QMP introspection didn't make it for 1.6.
>>
>> Thanks for your info. I will still wait for introspection.
>
> Can you help to review if the output of my patch v2 is ok for you?

OK. I am a newbie, but I will try to give some advice.

>
>> --
>> Regards
>> Qiao Nuohan
>


-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
                   ` (9 preceding siblings ...)
  2013-07-09  7:36 ` [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
@ 2013-12-13  2:07 ` Qiao Nuohan
  2013-12-13  2:25   ` Eric Blake
  10 siblings, 1 reply; 29+ messages in thread
From: Qiao Nuohan @ 2013-12-13  2:07 UTC (permalink / raw)
  To: Qiao Nuohan, lcapitulino, eblake, zhangxh, Amos
  Cc: stefanha, kumagai-atsushi, anderson, afaerber, qemu-devel

Hi, all

Would you please give some advice about how to continue my series?

My patches have stuck for several months, because I was not allowed to add an
option before introspection is implemented. After observing mails about
introspection, I find it is still not confirmed its implement way. Since I got
a deadline about this feature(in three months), I have to ask for some advice
about these patches.

First, I hope to confirm whether it is impossible to add an option to 'dump-
guest-memory'. If the answer is impossible, then should I still wait for
introspection or just change to add a new command?


On 07/09/2013 03:30 PM, Qiao Nuohan wrote:
> Hi, all
>
> The last version is here:
> http://lists.gnu.org/archive/html/qemu-devel/2013-05/msg03866.html
>
> Command 'dump-guest-memory' was introduced to dump guest's memory. But the
> vmcore's format is only elf32 or elf64. The message is here:
> http://lists.gnu.org/archive/html/qemu-devel/2012-04/msg03379.html
>
> Compared with migration, the missing of compression feature means regression
> to 'dump-guest-memory'. So we post these patches to make 'dump-guest-memory' be
> able to dump guest's in kdump-compressed format. Then vmcore can be much
> smaller, and easily to be delivered.
>
> The kdump-compressed format is *linux specific* *linux standard* crash dump
> format used in kdump framework. The kdump-compressed format is readable only
> with the crash utility, and it can be smaller than the ELF format because of
> the compression support. To get more detailed information about
> kdump-compressed format, please refer to the following URL:
> http://sourceforge.net/projects/makedumpfile/
>
> Note, similar to 'dump-guest-memory':
> 1. The guest should be x86 or x86_64. The other arch is not supported now.
> 2. If the OS is in the second kernel, gdb may not work well, and crash can
>     work by specifying '--machdep phys_addr=xxx' in the command line. The
>     reason is that the second kernel will update the page table, and we can
>     not get the page table for the first kernel.
> 3. The cpu's state is stored in QEMU note.
> 4. The vmcore are able to be compressed with zlib, lzo or snappy. zlib is
>     available by default, and option '--enable-lzo' or '--enable-snappy'
>     should be specified with 'configure' to make lzo or snappy available.
>
> Changelog:
> Changes from v4 to v5:
> 1. using flatten format to avoid using temporary files according to Stefan's
>     comments
> 2. Address Andreas's comments about coding style
>
> Changes from v3 to v4:
> 1. change to avoid conflict with Andreas's patches
> 2. rebase
>
> Changes from v2 to v3:
> 1. Address Eric's comment
>
> Changes from v1 to v2:
> 1. Address Eric&  Daniel's comment: fix manner of string copy.
> 2. Address Eric's comment: replace reinventing new constants by using the
>     ready-made ones accoring.
> 3. Address Andreas's comment: remove useless include.
>
> Qiao Nuohan (9):
>    dump: Add argument to write_elfxx_notes
>    dump: Add API to write header of flatten format
>    dump: Add API to write vmcore
>    dump: Add API to write elf notes to buffer
>    dump: add API to write dump header
>    dump: Add API to write dump_bitmap
>    dump: Add APIs to operate DataCache
>    dump: Add API to write dump pages
>    dump: Make kdump-compressed format available for 'dump-guest-memory'
>
>   configure             |   50 +++
>   dump.c                |  873 ++++++++++++++++++++++++++++++++++++++++++++++++-
>   hmp-commands.hx       |   12 +-
>   hmp.c                 |   23 ++-
>   include/sysemu/dump.h |  127 +++++++
>   qapi-schema.json      |   22 ++-
>   qmp-commands.hx       |    6 +-
>   7 files changed, 1088 insertions(+), 25 deletions(-)
>
>


-- 
Regards
Qiao Nuohan

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

* Re: [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format
  2013-12-13  2:07 ` Qiao Nuohan
@ 2013-12-13  2:25   ` Eric Blake
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Blake @ 2013-12-13  2:25 UTC (permalink / raw)
  To: Qiao Nuohan, lcapitulino, zhangxh, Amos
  Cc: stefanha, kumagai-atsushi, anderson, afaerber, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1775 bytes --]

On 12/12/2013 07:07 PM, Qiao Nuohan wrote:
> Hi, all
> 
> Would you please give some advice about how to continue my series?
> 
> My patches have stuck for several months, because I was not allowed to
> add an
> option before introspection is implemented. After observing mails about
> introspection, I find it is still not confirmed its implement way.

I can see several options:
1. Take over the introspection patches and push them through to completion
2. Come up with some alternative witness when your feature is available.
 Full-blown introspection of the entire QAPI schema is a heavy hammer,
and if we can have something simpler to use for just this case, but
still discoverable, then management can use that simpler method to learn
if this feature is present.  See for example how we added
'query-migrate-capabilities' as a way to add migration capabilities
without needing fullblown introspection.
3. Rebase your patches and post without waiting for any means of
discovery - maybe someone will still be interested enough in using the
patches even without management being able to programmatically determine
the availability.

This is a busy list; it doesn't mean your patch will be outright
rejected, but if you aren't actively pinging and rebasing it, the patch
gets less attention, so people assume no one wanted it.  Thanks for
reviving the discussion, and good luck with what you try next.
Personally, I think that both option 1 and 2 at the same time is worth
pursuing (I'd really like introspection, but introspection is a heavy
hammer so having something lighter weight for just your feature is also
worth having).

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

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

end of thread, other threads:[~2013-12-13  2:26 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-09  7:30 [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 1/9] dump: Add argument to write_elfxx_notes Qiao Nuohan
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 2/9] dump: Add API to write header of flatten format Qiao Nuohan
2013-07-16  2:06   ` Stefan Hajnoczi
2013-07-16  3:50     ` Qiao Nuohan
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 3/9] dump: Add API to write vmcore Qiao Nuohan
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 4/9] dump: Add API to write elf notes to buffer Qiao Nuohan
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 5/9] dump: add API to write dump header Qiao Nuohan
2013-07-16  2:18   ` Stefan Hajnoczi
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap Qiao Nuohan
2013-07-16  2:25   ` Stefan Hajnoczi
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 7/9] dump: Add APIs to operate DataCache Qiao Nuohan
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 8/9] dump: Add API to write dump pages Qiao Nuohan
2013-07-16  2:43   ` Stefan Hajnoczi
2013-07-16  3:40     ` Qiao Nuohan
2013-07-16 16:28     ` Eric Blake
2013-07-09  7:30 ` [Qemu-devel] [PATCH v5 9/9] dump: Make kdump-compressed format available for 'dump-guest-memory' Qiao Nuohan
2013-07-09  7:36 ` [Qemu-devel] [PATCH v5 0/9] Make 'dump-guest-memory' dump in kdump-compressed format Qiao Nuohan
2013-07-15  9:56   ` Qiao Nuohan
2013-07-16  2:45     ` Stefan Hajnoczi
2013-07-31  9:26   ` Qiao Nuohan
2013-07-31 12:23     ` Laszlo Ersek
2013-07-31 13:10       ` Luiz Capitulino
2013-08-02  3:25         ` Qiao Nuohan
2013-08-02  3:41           ` Amos Kong
2013-08-02  3:43             ` Qiao Nuohan
2013-08-02  3:37       ` Qiao Nuohan
2013-12-13  2:07 ` Qiao Nuohan
2013-12-13  2:25   ` Eric Blake

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.