From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36387) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W6M2A-0003Za-0N for qemu-devel@nongnu.org; Thu, 23 Jan 2014 10:17:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W6M22-0004fJ-Kz for qemu-devel@nongnu.org; Thu, 23 Jan 2014 10:17:33 -0500 Received: from e06smtp13.uk.ibm.com ([195.75.94.109]:33949) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W6M22-0004eD-9U for qemu-devel@nongnu.org; Thu, 23 Jan 2014 10:17:26 -0500 Received: from /spool/local by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 23 Jan 2014 15:17:25 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 6AA3B17D805F for ; Thu, 23 Jan 2014 15:17:40 +0000 (GMT) Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by b06cxnps4074.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s0NFHBDe5374424 for ; Thu, 23 Jan 2014 15:17:11 GMT Received: from d06av07.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s0NFHNad019574 for ; Thu, 23 Jan 2014 10:17:23 -0500 Received: from [9.156.34.41] (tumanova.moscow-rstl.ru.ibm.com [9.156.34.41] (may be forged)) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s0NFHMCF019555 for ; Thu, 23 Jan 2014 10:17:23 -0500 Message-ID: <52E13282.2080704@linux.vnet.ibm.com> Date: Thu, 23 Jan 2014 19:17:22 +0400 From: Ekaterina Tumanova MIME-Version: 1.0 References: <1389944779-31899-1-git-send-email-qiaonuohan@cn.fujitsu.com> <1389944779-31899-13-git-send-email-qiaonuohan@cn.fujitsu.com> In-Reply-To: <1389944779-31899-13-git-send-email-qiaonuohan@cn.fujitsu.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 12/13 v7] dump: make kdump-compressed format available for 'dump-guest-memory' List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org On 01/17/2014 11:46 AM, qiaonuohan wrote: > Make monitor command 'dump-guest-memory' be able to dump in kdump-compressed > format. The command's usage: > > dump [-p] protocol [begin] [length] [format] > > 'format' is used to specified the format of vmcore and can be: > 1. 'elf': ELF format, without compression > 2. 'kdump-zlib': kdump-compressed format, with zlib-compressed > 3. 'kdump-lzo': kdump-compressed format, with lzo-compressed > 4. 'kdump-snappy': kdump-compressed format, with snappy-compressed > Without 'format' being set, it is same as 'elf'. And if non-elf format is > specified, paging and filter is not allowed. > > Note: > 1. The kdump-compressed format is readable only with the crash utility and > makedumpfile, and it can be smaller than the ELF format because of the > compression support. > 2. The kdump-compressed format is the 6th edition. > > Signed-off-by: Qiao Nuohan > --- > dump.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++--- > hmp.c | 5 ++- > qapi-schema.json | 25 ++++++++++- > qmp-commands.hx | 7 ++- > 4 files changed, 156 insertions(+), 10 deletions(-) > > diff --git a/dump.c b/dump.c > index bb03ef7..dbf4bb6 100644 > --- a/dump.c > +++ b/dump.c > @@ -1449,6 +1449,64 @@ 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) | > + * | : | > + * |------------------------------------------| (not aligned by block) > + * | page data (pfn 0) | > + * | page data (pfn 1) | > + * | : | > + * +------------------------------------------+ > + */ > + > + ret = write_start_flat_header(s->fd); > + if (ret < 0) { > + dump_error(s, "dump: failed to write start flat header.\n"); > + 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; > + } > + > + ret = write_end_flat_header(s->fd); > + if (ret < 0) { > + dump_error(s, "dump: failed to write end flat header.\n"); > + return -1; > + } > + > + dump_completed(s); > + > + return 0; > +} > + > static ram_addr_t get_start_block(DumpState *s) > { > GuestPhysBlock *block; > @@ -1487,7 +1545,8 @@ static void get_max_mapnr(DumpState *s) > } > } > > -static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, > +static int dump_init(DumpState *s, int fd, bool has_format, > + DumpGuestMemoryFormat format, bool paging, bool has_filter, > int64_t begin, int64_t length, Error **errp) > { > CPUState *cpu; > @@ -1495,6 +1554,11 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, > Error *err = NULL; > int ret; > > + /* kdump-compressed is conflict with paging and filter */ > + if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) { > + assert(!paging && !has_filter); > + } > + > if (runstate_is_running()) { > vm_stop(RUN_STATE_SAVE_VM); > s->resume = true; > @@ -1565,6 +1629,28 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, > tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), s->page_size); > s->len_dump_bitmap = tmp * s->page_size; > > + /* 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; > + } > + > + return 0; > + } > + > if (s->has_filter) { > memory_mapping_filter(&s->list, s->begin, s->length); > } > @@ -1624,14 +1710,25 @@ 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; > DumpState *s; > int ret; > > + /* > + * kdump-compressed format need the whole memory dumped, so paging or > + * filter is not supported here. > + */ > + if ((has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) && > + (paging || has_begin || has_length)) { > + error_setg(errp, "kdump-compressed format doesn't support paging or " > + "filter"); > + return; > + } > if (has_begin && !has_length) { > error_set(errp, QERR_MISSING_PARAMETER, "length"); > return; > @@ -1641,6 +1738,19 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, > return; > } > > + /* check whether lzo/snappy is supported */ > +#ifndef CONFIG_LZO > + if (has_format && format == DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO) { > + error_setg(errp, "kdump-lzo is not available now"); > + } > +#endif When kdump-lzo is not available, command still writes a dump, which is half smaller then uncompressed one (and is read as partial dump), but is much bigger then the compressed one. Is it supposed to behave like that? Kate. > + > +#ifndef CONFIG_SNAPPY > + if (has_format && format == DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY) { > + error_setg(errp, "kdump-snappy is not available now"); > + } > +#endif > + > #if !defined(WIN32) > if (strstart(file, "fd:", &p)) { > fd = monitor_get_fd(cur_mon, p, errp); > @@ -1665,14 +1775,21 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, > > 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; > } > > - 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); > + } > } > > g_free(s); > diff --git a/hmp.c b/hmp.c > index 79f9c7d..5245e62 100644 > --- a/hmp.c > +++ b/hmp.c > @@ -1308,8 +1308,11 @@ 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"); > + /* kdump-compressed format is not supported for HMP */ > + bool has_format = false; > int64_t begin = 0; > int64_t length = 0; > + enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF; > char *prot; > > if (has_begin) { > @@ -1322,7 +1325,7 @@ 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); > + has_format, dump_format, &errp); > hmp_handle_error(mon, &errp); > g_free(prot); > } > diff --git a/qapi-schema.json b/qapi-schema.json > index f27c48a..52df894 100644 > --- a/qapi-schema.json > +++ b/qapi-schema.json > @@ -2677,6 +2677,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 lzo-compressed > +# > +# @kdump-snappy: kdump-compressed format with snappy-compressed > +# > +# Since: 2.0 > +## > +{ '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 > @@ -2712,13 +2730,18 @@ > # want to dump all guest's memory, please specify the start @begin > # and @length > # > +# @format: #optional if specified, the format of guest memory dump. But non-elf > +# format is conflict with paging and filter, ie. @paging, @begin and > +# @length is not allowed to be specified with @format at the same time > +# (since 2.0) > +# > # 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 02cc815..9158f22 100644 > --- a/qmp-commands.hx > +++ b/qmp-commands.hx > @@ -791,8 +791,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?,end: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, > @@ -813,6 +813,9 @@ 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, but non-elf formats will > + conflict with paging and filter, ie. begin and length(json-string) > > Example: >