|
|
958e1b |
From 7cc714c354fc4dbfaeca66156ca331f57bf9653e Mon Sep 17 00:00:00 2001
|
|
|
958e1b |
From: Laszlo Ersek <lersek@redhat.com>
|
|
|
958e1b |
Date: Fri, 7 Nov 2014 17:18:03 +0100
|
|
|
958e1b |
Subject: [PATCH 16/41] dump: make kdump-compressed format available for
|
|
|
958e1b |
'dump-guest-memory'
|
|
|
958e1b |
|
|
|
958e1b |
Message-id: <1415380693-16593-17-git-send-email-lersek@redhat.com>
|
|
|
958e1b |
Patchwork-id: 62202
|
|
|
958e1b |
O-Subject: [RHEL-7.1 qemu-kvm PATCH 16/26] dump: make kdump-compressed format available for 'dump-guest-memory'
|
|
|
958e1b |
Bugzilla: 1157798
|
|
|
958e1b |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
958e1b |
RH-Acked-by: Luiz Capitulino <lcapitulino@redhat.com>
|
|
|
958e1b |
RH-Acked-by: dgibson <dgibson@redhat.com>
|
|
|
958e1b |
|
|
|
958e1b |
From: qiaonuohan <qiaonuohan@cn.fujitsu.com>
|
|
|
958e1b |
|
|
|
958e1b |
Make monitor command 'dump-guest-memory' be able to dump in kdump-compressed
|
|
|
958e1b |
format. The command's usage:
|
|
|
958e1b |
|
|
|
958e1b |
dump [-p] protocol [begin] [length] [format]
|
|
|
958e1b |
|
|
|
958e1b |
'format' is used to specified the format of vmcore and can be:
|
|
|
958e1b |
1. 'elf': ELF format, without compression
|
|
|
958e1b |
2. 'kdump-zlib': kdump-compressed format, with zlib-compressed
|
|
|
958e1b |
3. 'kdump-lzo': kdump-compressed format, with lzo-compressed
|
|
|
958e1b |
4. 'kdump-snappy': kdump-compressed format, with snappy-compressed
|
|
|
958e1b |
Without 'format' being set, it is same as 'elf'. And if non-elf format is
|
|
|
958e1b |
specified, paging and filter is not allowed.
|
|
|
958e1b |
|
|
|
958e1b |
Note:
|
|
|
958e1b |
1. The kdump-compressed format is readable only with the crash utility and
|
|
|
958e1b |
makedumpfile, and it can be smaller than the ELF format because of the
|
|
|
958e1b |
compression support.
|
|
|
958e1b |
2. The kdump-compressed format is the 6th edition.
|
|
|
958e1b |
|
|
|
958e1b |
Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
|
|
|
958e1b |
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
958e1b |
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
|
|
|
958e1b |
(cherry picked from commit b53ccc30c40df52d192e469a86c188a8649c6df3)
|
|
|
958e1b |
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
958e1b |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
958e1b |
---
|
|
|
958e1b |
dump.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
|
|
958e1b |
hmp.c | 5 ++-
|
|
|
958e1b |
qapi-schema.json | 25 ++++++++++-
|
|
|
958e1b |
qmp-commands.hx | 7 ++-
|
|
|
958e1b |
4 files changed, 158 insertions(+), 10 deletions(-)
|
|
|
958e1b |
|
|
|
958e1b |
diff --git a/dump.c b/dump.c
|
|
|
958e1b |
index fc5530f..c0d5877 100644
|
|
|
958e1b |
--- a/dump.c
|
|
|
958e1b |
+++ b/dump.c
|
|
|
958e1b |
@@ -1449,6 +1449,64 @@ out:
|
|
|
958e1b |
return ret;
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
+static int create_kdump_vmcore(DumpState *s)
|
|
|
958e1b |
+{
|
|
|
958e1b |
+ int ret;
|
|
|
958e1b |
+
|
|
|
958e1b |
+ /*
|
|
|
958e1b |
+ * the kdump-compressed format is:
|
|
|
958e1b |
+ * File offset
|
|
|
958e1b |
+ * +------------------------------------------+ 0x0
|
|
|
958e1b |
+ * | main header (struct disk_dump_header) |
|
|
|
958e1b |
+ * |------------------------------------------+ block 1
|
|
|
958e1b |
+ * | sub header (struct kdump_sub_header) |
|
|
|
958e1b |
+ * |------------------------------------------+ block 2
|
|
|
958e1b |
+ * | 1st-dump_bitmap |
|
|
|
958e1b |
+ * |------------------------------------------+ block 2 + X blocks
|
|
|
958e1b |
+ * | 2nd-dump_bitmap | (aligned by block)
|
|
|
958e1b |
+ * |------------------------------------------+ block 2 + 2 * X blocks
|
|
|
958e1b |
+ * | page desc for pfn 0 (struct page_desc) | (aligned by block)
|
|
|
958e1b |
+ * | page desc for pfn 1 (struct page_desc) |
|
|
|
958e1b |
+ * | : |
|
|
|
958e1b |
+ * |------------------------------------------| (not aligned by block)
|
|
|
958e1b |
+ * | page data (pfn 0) |
|
|
|
958e1b |
+ * | page data (pfn 1) |
|
|
|
958e1b |
+ * | : |
|
|
|
958e1b |
+ * +------------------------------------------+
|
|
|
958e1b |
+ */
|
|
|
958e1b |
+
|
|
|
958e1b |
+ ret = write_start_flat_header(s->fd);
|
|
|
958e1b |
+ if (ret < 0) {
|
|
|
958e1b |
+ dump_error(s, "dump: failed to write start flat header.\n");
|
|
|
958e1b |
+ return -1;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
+ ret = write_dump_header(s);
|
|
|
958e1b |
+ if (ret < 0) {
|
|
|
958e1b |
+ return -1;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
+ ret = write_dump_bitmap(s);
|
|
|
958e1b |
+ if (ret < 0) {
|
|
|
958e1b |
+ return -1;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
+ ret = write_dump_pages(s);
|
|
|
958e1b |
+ if (ret < 0) {
|
|
|
958e1b |
+ return -1;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
+ ret = write_end_flat_header(s->fd);
|
|
|
958e1b |
+ if (ret < 0) {
|
|
|
958e1b |
+ dump_error(s, "dump: failed to write end flat header.\n");
|
|
|
958e1b |
+ return -1;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
+ dump_completed(s);
|
|
|
958e1b |
+
|
|
|
958e1b |
+ return 0;
|
|
|
958e1b |
+}
|
|
|
958e1b |
+
|
|
|
958e1b |
static ram_addr_t get_start_block(DumpState *s)
|
|
|
958e1b |
{
|
|
|
958e1b |
GuestPhysBlock *block;
|
|
|
958e1b |
@@ -1485,7 +1543,8 @@ static void get_max_mapnr(DumpState *s)
|
|
|
958e1b |
s->max_mapnr = paddr_to_pfn(last_block->target_end, s->page_shift);
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
-static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
|
|
|
958e1b |
+static int dump_init(DumpState *s, int fd, bool has_format,
|
|
|
958e1b |
+ DumpGuestMemoryFormat format, bool paging, bool has_filter,
|
|
|
958e1b |
int64_t begin, int64_t length, Error **errp)
|
|
|
958e1b |
{
|
|
|
958e1b |
CPUArchState *env;
|
|
|
958e1b |
@@ -1493,6 +1552,11 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
|
|
|
958e1b |
Error *err = NULL;
|
|
|
958e1b |
int ret;
|
|
|
958e1b |
|
|
|
958e1b |
+ /* kdump-compressed is conflict with paging and filter */
|
|
|
958e1b |
+ if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
|
|
|
958e1b |
+ assert(!paging && !has_filter);
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
if (runstate_is_running()) {
|
|
|
958e1b |
vm_stop(RUN_STATE_SAVE_VM);
|
|
|
958e1b |
s->resume = true;
|
|
|
958e1b |
@@ -1563,6 +1627,28 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
|
|
|
958e1b |
tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), s->page_size);
|
|
|
958e1b |
s->len_dump_bitmap = tmp * s->page_size;
|
|
|
958e1b |
|
|
|
958e1b |
+ /* init for kdump-compressed format */
|
|
|
958e1b |
+ if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
|
|
|
958e1b |
+ switch (format) {
|
|
|
958e1b |
+ case DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB:
|
|
|
958e1b |
+ s->flag_compress = DUMP_DH_COMPRESSED_ZLIB;
|
|
|
958e1b |
+ break;
|
|
|
958e1b |
+
|
|
|
958e1b |
+ case DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO:
|
|
|
958e1b |
+ s->flag_compress = DUMP_DH_COMPRESSED_LZO;
|
|
|
958e1b |
+ break;
|
|
|
958e1b |
+
|
|
|
958e1b |
+ case DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY:
|
|
|
958e1b |
+ s->flag_compress = DUMP_DH_COMPRESSED_SNAPPY;
|
|
|
958e1b |
+ break;
|
|
|
958e1b |
+
|
|
|
958e1b |
+ default:
|
|
|
958e1b |
+ s->flag_compress = 0;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
+ return 0;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
if (s->has_filter) {
|
|
|
958e1b |
memory_mapping_filter(&s->list, s->begin, s->length);
|
|
|
958e1b |
}
|
|
|
958e1b |
@@ -1622,14 +1708,25 @@ cleanup:
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
|
|
|
958e1b |
- int64_t begin, bool has_length, int64_t length,
|
|
|
958e1b |
- Error **errp)
|
|
|
958e1b |
+ int64_t begin, bool has_length,
|
|
|
958e1b |
+ int64_t length, bool has_format,
|
|
|
958e1b |
+ DumpGuestMemoryFormat format, Error **errp)
|
|
|
958e1b |
{
|
|
|
958e1b |
const char *p;
|
|
|
958e1b |
int fd = -1;
|
|
|
958e1b |
DumpState *s;
|
|
|
958e1b |
int ret;
|
|
|
958e1b |
|
|
|
958e1b |
+ /*
|
|
|
958e1b |
+ * kdump-compressed format need the whole memory dumped, so paging or
|
|
|
958e1b |
+ * filter is not supported here.
|
|
|
958e1b |
+ */
|
|
|
958e1b |
+ if ((has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) &&
|
|
|
958e1b |
+ (paging || has_begin || has_length)) {
|
|
|
958e1b |
+ error_setg(errp, "kdump-compressed format doesn't support paging or "
|
|
|
958e1b |
+ "filter");
|
|
|
958e1b |
+ return;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
if (has_begin && !has_length) {
|
|
|
958e1b |
error_set(errp, QERR_MISSING_PARAMETER, "length");
|
|
|
958e1b |
return;
|
|
|
958e1b |
@@ -1639,6 +1736,21 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
|
|
|
958e1b |
return;
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
+ /* check whether lzo/snappy is supported */
|
|
|
958e1b |
+#ifndef CONFIG_LZO
|
|
|
958e1b |
+ if (has_format && format == DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO) {
|
|
|
958e1b |
+ error_setg(errp, "kdump-lzo is not available now");
|
|
|
958e1b |
+ return;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+#endif
|
|
|
958e1b |
+
|
|
|
958e1b |
+#ifndef CONFIG_SNAPPY
|
|
|
958e1b |
+ if (has_format && format == DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY) {
|
|
|
958e1b |
+ error_setg(errp, "kdump-snappy is not available now");
|
|
|
958e1b |
+ return;
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+#endif
|
|
|
958e1b |
+
|
|
|
958e1b |
#if !defined(WIN32)
|
|
|
958e1b |
if (strstart(file, "fd:", &p)) {
|
|
|
958e1b |
fd = monitor_get_fd(cur_mon, p, errp);
|
|
|
958e1b |
@@ -1663,14 +1775,21 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
|
|
|
958e1b |
|
|
|
958e1b |
s = g_malloc0(sizeof(DumpState));
|
|
|
958e1b |
|
|
|
958e1b |
- ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
|
|
|
958e1b |
+ ret = dump_init(s, fd, has_format, format, paging, has_begin,
|
|
|
958e1b |
+ begin, length, errp);
|
|
|
958e1b |
if (ret < 0) {
|
|
|
958e1b |
g_free(s);
|
|
|
958e1b |
return;
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
- if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
|
|
|
958e1b |
- error_set(errp, QERR_IO_ERROR);
|
|
|
958e1b |
+ if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
|
|
|
958e1b |
+ if (create_kdump_vmcore(s) < 0 && !error_is_set(s->errp)) {
|
|
|
958e1b |
+ error_set(errp, QERR_IO_ERROR);
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+ } else {
|
|
|
958e1b |
+ if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
|
|
|
958e1b |
+ error_set(errp, QERR_IO_ERROR);
|
|
|
958e1b |
+ }
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
g_free(s);
|
|
|
958e1b |
diff --git a/hmp.c b/hmp.c
|
|
|
958e1b |
index b723b26..1805926 100644
|
|
|
958e1b |
--- a/hmp.c
|
|
|
958e1b |
+++ b/hmp.c
|
|
|
958e1b |
@@ -1195,8 +1195,11 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
|
|
958e1b |
const char *file = qdict_get_str(qdict, "filename");
|
|
|
958e1b |
bool has_begin = qdict_haskey(qdict, "begin");
|
|
|
958e1b |
bool has_length = qdict_haskey(qdict, "length");
|
|
|
958e1b |
+ /* kdump-compressed format is not supported for HMP */
|
|
|
958e1b |
+ bool has_format = false;
|
|
|
958e1b |
int64_t begin = 0;
|
|
|
958e1b |
int64_t length = 0;
|
|
|
958e1b |
+ enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
|
|
|
958e1b |
char *prot;
|
|
|
958e1b |
|
|
|
958e1b |
if (has_begin) {
|
|
|
958e1b |
@@ -1209,7 +1212,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
|
|
958e1b |
prot = g_strconcat("file:", file, NULL);
|
|
|
958e1b |
|
|
|
958e1b |
qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
|
|
|
958e1b |
- &errp);
|
|
|
958e1b |
+ has_format, dump_format, &errp);
|
|
|
958e1b |
hmp_handle_error(mon, &errp);
|
|
|
958e1b |
g_free(prot);
|
|
|
958e1b |
}
|
|
|
958e1b |
diff --git a/qapi-schema.json b/qapi-schema.json
|
|
|
958e1b |
index d3d4e57..8f81c76 100644
|
|
|
958e1b |
--- a/qapi-schema.json
|
|
|
958e1b |
+++ b/qapi-schema.json
|
|
|
958e1b |
@@ -2578,6 +2578,24 @@
|
|
|
958e1b |
{ 'command': 'device_del', 'data': {'id': 'str'} }
|
|
|
958e1b |
|
|
|
958e1b |
##
|
|
|
958e1b |
+# @DumpGuestMemoryFormat:
|
|
|
958e1b |
+#
|
|
|
958e1b |
+# An enumeration of guest-memory-dump's format.
|
|
|
958e1b |
+#
|
|
|
958e1b |
+# @elf: elf format
|
|
|
958e1b |
+#
|
|
|
958e1b |
+# @kdump-zlib: kdump-compressed format with zlib-compressed
|
|
|
958e1b |
+#
|
|
|
958e1b |
+# @kdump-lzo: kdump-compressed format with lzo-compressed
|
|
|
958e1b |
+#
|
|
|
958e1b |
+# @kdump-snappy: kdump-compressed format with snappy-compressed
|
|
|
958e1b |
+#
|
|
|
958e1b |
+# Since: 2.0
|
|
|
958e1b |
+##
|
|
|
958e1b |
+{ 'enum': 'DumpGuestMemoryFormat',
|
|
|
958e1b |
+ 'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy' ] }
|
|
|
958e1b |
+
|
|
|
958e1b |
+##
|
|
|
958e1b |
# @dump-guest-memory
|
|
|
958e1b |
#
|
|
|
958e1b |
# Dump guest's memory to vmcore. It is a synchronous operation that can take
|
|
|
958e1b |
@@ -2613,13 +2631,18 @@
|
|
|
958e1b |
# want to dump all guest's memory, please specify the start @begin
|
|
|
958e1b |
# and @length
|
|
|
958e1b |
#
|
|
|
958e1b |
+# @format: #optional if specified, the format of guest memory dump. But non-elf
|
|
|
958e1b |
+# format is conflict with paging and filter, ie. @paging, @begin and
|
|
|
958e1b |
+# @length is not allowed to be specified with non-elf @format at the
|
|
|
958e1b |
+# same time (since 2.0)
|
|
|
958e1b |
+#
|
|
|
958e1b |
# Returns: nothing on success
|
|
|
958e1b |
#
|
|
|
958e1b |
# Since: 1.2
|
|
|
958e1b |
##
|
|
|
958e1b |
{ 'command': 'dump-guest-memory',
|
|
|
958e1b |
'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
|
|
|
958e1b |
- '*length': 'int' } }
|
|
|
958e1b |
+ '*length': 'int', '*format': 'DumpGuestMemoryFormat' } }
|
|
|
958e1b |
|
|
|
958e1b |
##
|
|
|
958e1b |
# @netdev_add:
|
|
|
958e1b |
diff --git a/qmp-commands.hx b/qmp-commands.hx
|
|
|
958e1b |
index e164ff8..61aa3bf 100644
|
|
|
958e1b |
--- a/qmp-commands.hx
|
|
|
958e1b |
+++ b/qmp-commands.hx
|
|
|
958e1b |
@@ -885,8 +885,8 @@ EQMP
|
|
|
958e1b |
|
|
|
958e1b |
{
|
|
|
958e1b |
.name = "dump-guest-memory",
|
|
|
958e1b |
- .args_type = "paging:b,protocol:s,begin:i?,end:i?",
|
|
|
958e1b |
- .params = "-p protocol [begin] [length]",
|
|
|
958e1b |
+ .args_type = "paging:b,protocol:s,begin:i?,end:i?,format:s?",
|
|
|
958e1b |
+ .params = "-p protocol [begin] [length] [format]",
|
|
|
958e1b |
.help = "dump guest memory to file",
|
|
|
958e1b |
.user_print = monitor_user_noop,
|
|
|
958e1b |
.mhandler.cmd_new = qmp_marshal_input_dump_guest_memory,
|
|
|
958e1b |
@@ -907,6 +907,9 @@ Arguments:
|
|
|
958e1b |
with length together (json-int)
|
|
|
958e1b |
- "length": the memory size, in bytes. It's optional, and should be specified
|
|
|
958e1b |
with begin together (json-int)
|
|
|
958e1b |
+- "format": the format of guest memory dump. It's optional, and can be
|
|
|
958e1b |
+ elf|kdump-zlib|kdump-lzo|kdump-snappy, but non-elf formats will
|
|
|
958e1b |
+ conflict with paging and filter, ie. begin and length (json-string)
|
|
|
958e1b |
|
|
|
958e1b |
Example:
|
|
|
958e1b |
|
|
|
958e1b |
--
|
|
|
958e1b |
1.8.3.1
|
|
|
958e1b |
|