qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 9/9] Make monitor command 'dump-guest-memory' dump i


From: Qiao Nuohan
Subject: [Qemu-devel] [PATCH 9/9] Make monitor command 'dump-guest-memory' dump in kdump-compressed format
Date: Tue, 7 May 2013 15:16:47 +0800

Make monitor command 'dump-guest-memory' dump in kdump-compressed format.
The command's usage:
  dump [-p] protocol [flags] [begin] [length]
With 'flags' set, the core file will be in kdump-compress format, and without
it, the format is ELF. 'flags' can be:
1. FLAG_DUMP_COMPRESS_ZLIB(0x1), compress vmcore with zlib
2. FLAG_DUMP_COMPRESS_LZO(0x2), compress vmcore with lzo
3. FLAG_DUMP_COMPRESS_SNAPPY(0x4), compress vmcore with snappy

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 <address@hidden>
Signed-off-by: Zhang Xiaohe <address@hidden>
---
 configure             |   50 +++++++++++++++++++++++++
 dump.c                |   96 ++++++++++++++++++++++++++++++++++++++++++++-----
 hmp-commands.hx       |    8 +++--
 hmp.c                 |    9 ++++-
 include/sysemu/dump.h |    8 ++++
 qapi-schema.json      |    6 ++-
 qmp-commands.hx       |    5 ++-
 7 files changed, 164 insertions(+), 18 deletions(-)

diff --git a/configure b/configure
index e818e8b..f4415c9 100755
--- a/configure
+++ b/configure
@@ -229,6 +229,8 @@ libusb=""
 usb_redir=""
 glx=""
 zlib="yes"
+lzo="no"
+snappy="no"
 guest_agent="yes"
 want_tools="yes"
 libiscsi=""
@@ -898,6 +900,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"
@@ -1494,6 +1500,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
@@ -3883,6 +3925,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 aa83744..fd81c07 100644
--- a/dump.c
+++ b/dump.c
@@ -1014,6 +1014,16 @@ static int create_header64(DumpState *s)
     return 0;
 }
 
+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);
+    }
+}
+
 /*
  * gather data of header and sub header
  */
@@ -1377,12 +1387,14 @@ out:
     return ret;
 }
 
-static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
-                     int64_t begin, int64_t length, Error **errp)
+static int dump_init(DumpState *s, int fd, bool has_flags, int64_t flags,
+                    bool paging, bool has_filter, int64_t begin, int64_t 
length,
+                    Error **errp)
 {
     CPUArchState *env;
     int nr_cpus;
     int ret;
+    unsigned long tmp;
 
     if (runstate_is_running()) {
         vm_stop(RUN_STATE_SAVE_VM);
@@ -1437,6 +1449,56 @@ 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_flags) {
+        switch (flags) {
+            case FLAG_DUMP_COMPRESS_ZLIB:
+                s->flag_compress = DUMP_DH_COMPRESSED_ZLIB;
+                break;
+            case FLAG_DUMP_COMPRESS_LZO:
+                s->flag_compress = DUMP_DH_COMPRESSED_LZO;
+                break;
+            case FLAG_DUMP_COMPRESS_SNAPPY:
+                s->flag_compress = DUMP_DH_COMPRESSED_SNAPPY;
+                break;
+            default:
+                s->flag_compress = 0;
+        }
+
+        s->nr_cpus = nr_cpus;
+        s->page_size = PAGE_SIZE;
+        s->page_shift = ffs(s->page_size) - 1;
+
+        get_max_mapnr(s);
+
+        tmp = divideup(divideup(s->max_mapnr, BITPERBYTE), s->page_size);
+        s->len_dump_bitmap = tmp * s->page_size * 2;
+
+        /*
+         * gather data of header, dump_bitmap, page_desc and page_data, then
+         * cache them in tmp files
+         */
+        ret = create_header(s);
+        if (ret < 0) {
+            error_set(errp, QERR_UNSUPPORTED);
+            goto cleanup;
+        }
+
+        ret = create_dump_bitmap(s);
+        if (ret < 0) {
+            error_set(errp, QERR_UNSUPPORTED);
+            goto cleanup;
+        }
+
+        ret = create_pages(s);
+        if (ret < 0) {
+            error_set(errp, QERR_UNSUPPORTED);
+            goto cleanup;
+        }
+
+        return 0;
+    }
+
     if (s->has_filter) {
         memory_mapping_filter(&s->list, s->begin, s->length);
     }
@@ -1510,15 +1572,22 @@ static void clean_state(DumpState *s)
     free_cache_data(s->page_data);
 }
 
-void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
-                           int64_t begin, bool has_length, int64_t length,
-                           Error **errp)
+void qmp_dump_guest_memory(bool paging, const char *file,
+                            bool has_flags, int64_t flags,
+                            bool has_begin, int64_t begin,
+                            bool has_length, int64_t length, Error **errp)
 {
     const char *p;
     int fd = -1;
     DumpState *s;
     int ret;
 
+    /* kdump-compressed format is invalid with paging or filter */
+    if (has_flags && (paging || has_begin || has_length)) {
+        error_set(errp, QERR_INVALID_PARAMETER_COMBINATION);
+        return;
+    }
+
     if (has_begin && !has_length) {
         error_set(errp, QERR_MISSING_PARAMETER, "length");
         return;
@@ -1550,17 +1619,26 @@ void qmp_dump_guest_memory(bool paging, const char 
*file, bool has_begin,
         return;
     }
 
-    s = g_malloc(sizeof(DumpState));
+    /* initialize DumpState to zero */
+    s = g_malloc0(sizeof(DumpState));
 
-    ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
+    ret = dump_init(s, fd, has_flags, flags, paging, has_begin, begin, length, 
errp);
     if (ret < 0) {
         g_free(s);
         return;
     }
 
-    if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
-        error_set(errp, QERR_IO_ERROR);
+    if (has_flags) {
+        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);
+        }
     }
 
+    clean_state(s);
+
     g_free(s);
 }
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9cea415..c278a50 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -992,9 +992,10 @@ ETEXI
 #if defined(CONFIG_HAVE_CORE_DUMP)
     {
         .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,flags:i?,begin:i?,length:i?",
+        .params     = "[-p] filename [flags] [begin] [length]",
         .help       = "dump guest memory to file"
+                      "\n\t\t\t flags: the type of compression"
                       "\n\t\t\t begin(optional): the starting physical address"
                       "\n\t\t\t length(optional): the memory size, in bytes",
         .mhandler.cmd = hmp_dump_guest_memory,
@@ -1002,12 +1003,13 @@ ETEXI
 
 
 STEXI
address@hidden dump-guest-memory [-p] @var{protocol} @var{begin} @var{length}
address@hidden dump-guest-memory [-p] @var{protocol} @var{flags} @var{begin} 
@var{length}
 @findex dump-guest-memory
 Dump guest memory to @var{protocol}. The file can be processed with crash or
 gdb.
   filename: dump file name
     paging: do paging to get guest's memory mapping
+     flags: an optional parameter which describes the format of dump.
      begin: the starting physical address. It's optional, and should be
             specified with length together.
     length: the memory size, in bytes. It's optional, and should be specified
diff --git a/hmp.c b/hmp.c
index 4fb76ec..c7a7c2f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1183,12 +1183,17 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict 
*qdict)
     Error *errp = NULL;
     int paging = qdict_get_try_bool(qdict, "paging", 0);
     const char *file = qdict_get_str(qdict, "filename");
+    bool has_flags = qdict_haskey(qdict, "flags");
     bool has_begin = qdict_haskey(qdict, "begin");
     bool has_length = qdict_haskey(qdict, "length");
+    int64_t flags = 0;
     int64_t begin = 0;
     int64_t length = 0;
     char *prot;
 
+    if (has_flags) {
+        flags = qdict_get_int(qdict, "flags");
+    }
     if (has_begin) {
         begin = qdict_get_int(qdict, "begin");
     }
@@ -1198,8 +1203,8 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict 
*qdict)
 
     prot = g_strconcat("file:", file, NULL);
 
-    qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
-                          &errp);
+    qmp_dump_guest_memory(paging, prot, has_flags, flags, has_begin, begin,
+                            has_length, length, &errp);
     hmp_handle_error(mon, &errp);
     g_free(prot);
 }
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 4913468..b860ff0 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -38,6 +38,13 @@
 #endif
 
 /*
+ * dump format
+ */
+#define FLAG_DUMP_COMPRESS_ZLIB     (0x1)   /* compressed with zlib */
+#define FLAG_DUMP_COMPRESS_LZO      (0x2)   /* compressed with lzo */
+#define FLAG_DUMP_COMPRESS_SNAPPY   (0x4)   /* compressed with snappy */
+
+/*
  * flag used in page desc of kdump-compressed format
  */
 #define DUMP_DH_COMPRESSED_ZLIB     (0x1)
@@ -47,6 +54,7 @@
 #define KDUMP_SIGNATURE             "KDUMP   "
 #define SIG_LEN                     (sizeof(KDUMP_SIGNATURE) - 1)
 #define DISKDUMP_HEADER_BLOCKS      (1)
+#define PAGE_SIZE                   (4096)
 #define PHYS_BASE                   (0)
 #define DUMP_LEVEL                  (1)
 #define TMP_BUF_SIZE                (1024)
diff --git a/qapi-schema.json b/qapi-schema.json
index 7797400..b1d0c5d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2410,6 +2410,8 @@
 #            2. fd: the protocol starts with "fd:", and the following string
 #               is the fd's name.
 #
+# @flags: #optional if specified, the format of dump file.
+#
 # @begin: #optional if specified, the starting physical address.
 #
 # @length: #optional if specified, the memory size, in bytes. If you don't
@@ -2421,8 +2423,8 @@
 # Since: 1.2
 ##
 { 'command': 'dump-guest-memory',
-  'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
-            '*length': 'int' } }
+  'data': { 'paging': 'bool', 'protocol': 'str', '*flags': 'int',
+            '*begin': 'int', '*length': 'int' } }
 
 ##
 # @netdev_add:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ffd130e..93dd61c 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,flags:i?,begin:i?,length:i?",
+        .params     = "-p protocol [flags] [begin] [length]",
         .help       = "dump guest memory to file",
         .user_print = monitor_user_noop,
         .mhandler.cmd_new = qmp_marshal_input_dump_guest_memory,
@@ -806,6 +806,7 @@ Arguments:
 - "paging": do paging to get guest's memory mapping (json-bool)
 - "protocol": destination file(started with "file:") or destination file
               descriptor (started with "fd:") (json-string)
+- "flags": dump flag. It's optional, and describes the format of dump 
(json-int)
 - "begin": the starting physical address. It's optional, and should be 
specified
            with length together (json-int)
 - "length": the memory size, in bytes. It's optional, and should be specified
-- 
1.7.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]