From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:58668) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UZcjP-0003yu-Aw for qemu-devel@nongnu.org; Tue, 07 May 2013 03:54:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UZcjK-0002mY-LT for qemu-devel@nongnu.org; Tue, 07 May 2013 03:54:39 -0400 Received: from fgwmail7.fujitsu.co.jp ([192.51.44.37]:39792) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UZcjJ-0002mR-Rk for qemu-devel@nongnu.org; Tue, 07 May 2013 03:54:34 -0400 Received: from fgwmail6.fujitsu.co.jp (fgwmail6.fujitsu.co.jp [192.51.44.36]) by fgwmail7.fujitsu.co.jp (Postfix) with ESMTP id 6BDC11794801 for ; Tue, 7 May 2013 16:16:50 +0900 (JST) Received: from m2.gw.fujitsu.co.jp (unknown [10.0.50.72]) by fgwmail6.fujitsu.co.jp (Postfix) with ESMTP id 6521F3EE0C1 for ; Tue, 7 May 2013 16:16:49 +0900 (JST) Received: from smail (m2 [127.0.0.1]) by outgoing.m2.gw.fujitsu.co.jp (Postfix) with ESMTP id 556A045DE54 for ; Tue, 7 May 2013 16:16:49 +0900 (JST) Received: from s2.gw.fujitsu.co.jp (s2.gw.fujitsu.co.jp [10.0.50.92]) by m2.gw.fujitsu.co.jp (Postfix) with ESMTP id 3251C45DE53 for ; Tue, 7 May 2013 16:16:49 +0900 (JST) Received: from s2.gw.fujitsu.co.jp (localhost.localdomain [127.0.0.1]) by s2.gw.fujitsu.co.jp (Postfix) with ESMTP id 22C641DB8041 for ; Tue, 7 May 2013 16:16:49 +0900 (JST) Received: from s00.fujitsu.com (s00.gw.fujitsu.co.jp [133.161.11.15]) by s2.gw.fujitsu.co.jp (Postfix) with ESMTP id D54141DB803E for ; Tue, 7 May 2013 16:16:48 +0900 (JST) Received: from s00.gw.fujitsu.co.jp (localhost [127.0.0.1]) by s00.fujitsu.com (Postfix) with ESMTP id 58BCDAC29B for ; Tue, 7 May 2013 16:16:46 +0900 (JST) Received: from localhost.localdomain (unknown [10.167.226.120]) by s00.fujitsu.com (Postfix) with ESMTP id E03B3AC047 for ; Tue, 7 May 2013 16:16:45 +0900 (JST) From: Qiao Nuohan Date: Tue, 7 May 2013 15:16:46 +0800 Message-Id: <1367911007-13990-9-git-send-email-qiaonuohan@cn.fujitsu.com> In-Reply-To: <1367911007-13990-1-git-send-email-qiaonuohan@cn.fujitsu.com> References: <1367911007-13990-1-git-send-email-qiaonuohan@cn.fujitsu.com> Subject: [Qemu-devel] [PATCH 8/9] Add API to write header, bitmap and page into vmcore List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Qiao Nuohan The following patch will use these functions to write cached data into vmcore. Header is cached in DumpState, and bitmap and page are cached in tmp files. Signed-off-by: Qiao Nuohan Reviewed-by: Zhang Xiaohe --- dump.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++ include/sysemu/dump.h | 1 + 2 files changed, 248 insertions(+), 0 deletions(-) diff --git a/dump.c b/dump.c index c372113..aa83744 100644 --- a/dump.c +++ b/dump.c @@ -66,6 +66,34 @@ static void dump_error(DumpState *s, const char *reason) dump_cleanup(s); } +/* + * write 'size' of 'c' to dump file + */ +static int fill_space(size_t size, int c, void *opaque) +{ + DumpState *s = opaque; + char tmpbuf[TMP_BUF_SIZE]; + size_t fill_size; + size_t written_size; + + memset(&tmpbuf, c, TMP_BUF_SIZE); + + while (size) { + if (size > TMP_BUF_SIZE) + fill_size = TMP_BUF_SIZE; + else + fill_size = size; + + size -= fill_size; + + written_size = qemu_write_full(s->fd, tmpbuf, fill_size); + if (written_size != fill_size) + return -1; + } + + return 0; +} + static int fd_write_vmcore(void *buf, size_t size, void *opaque) { DumpState *s = opaque; @@ -671,6 +699,225 @@ static ram_addr_t get_start_block(DumpState *s) return -1; } +static int write_dump_header(DumpState *s) +{ + int ret; + void *dh; + void *kh; + + /* write common header */ + dh = s->dh; + + if (s->dump_info.d_machine == EM_386) { + ret = fd_write_vmcore(dh, sizeof(struct disk_dump_header32), s); + if (ret < 0) { + dump_error(s, "dump: failed to write disk dump header.\n"); + return -1; + } + } else { + ret = fd_write_vmcore(dh, sizeof(struct disk_dump_header64), s); + if (ret < 0) { + dump_error(s, "dump: failed to write disk dump header.\n"); + return -1; + } + } + + /* fill gap between command header and sub header */ + ret = fill_space(s->offset_sub_header, 0, s); + if (ret < 0) { + dump_error(s, "dump: failed to fill the space between header and sub header.\n"); + return -1; + } + + /* write sub header */ + kh = s->kh; + + if (s->dump_info.d_machine == EM_386) { + ret = fd_write_vmcore(kh, sizeof(struct kdump_sub_header32), s); + if (ret < 0) { + dump_error(s, "dump: failed to write kdump sub header.\n"); + return -1; + } + } else { + ret = fd_write_vmcore(kh, sizeof(struct kdump_sub_header64), s); + if (ret < 0) { + dump_error(s, "dump: failed to write kdump sub header.\n"); + return -1; + } + } + + /* write note */ + if (s->dump_info.d_class == ELFCLASS64) { + if (write_elf64_notes(s) < 0) { + return -1; + } + } else { + if (write_elf32_notes(s) < 0) { + return -1; + } + } + + return 0; +} + +static int write_dump_bitmap(DumpState *s) +{ + struct cache_data bm; + long buf_size; + int ret; + int no_bitmap; + + /* fill gap between header and dump_bitmap */ + ret = fill_space(s->offset_dump_bitmap, 0, s); + if (ret < 0) { + dump_error(s, "dump: failed to fill the space between header and dump_bitmap.\n"); + goto out; + } + + bm.buf = g_malloc0(TMP_BUF_SIZE); + + /* write dump_bitmap1 */ + bm.fd = s->dump_bitmap1->fd; + no_bitmap = 1; + +again: + buf_size = s->len_dump_bitmap / 2; + bm.offset = 0; + + while (buf_size > 0) { + if (buf_size >= TMP_BUF_SIZE) + bm.cache_size = TMP_BUF_SIZE; + else + bm.cache_size = buf_size; + + ret = read_cache(&bm); + if (ret < 0) + goto out; + + ret = fd_write_vmcore(bm.buf, bm.cache_size, s); + if (ret < 0) + goto out; + + buf_size -= bm.cache_size; + } + + /* switch to dump_bitmap2 */ + if (no_bitmap == 1) { + no_bitmap = 2; + bm.fd = s->dump_bitmap2->fd; + goto again; + } + + return 0; + +out: + if (bm.buf) + g_free(bm.buf); + + return -1; +} + +static int write_dump_pages(DumpState *s) +{ + struct cache_data page; + unsigned long long total_size; + int is_page_desc; + int ret; + + page.buf = g_malloc0(TMP_BUF_SIZE); + + /* write page_desc */ + is_page_desc = 1; + total_size = s->page_desc_size; + page.fd = s->page_desc->fd; + page.offset = s->page_desc->offset; + +again: + while (total_size > 0) { + if (total_size > TMP_BUF_SIZE) + page.cache_size = TMP_BUF_SIZE; + else + page.cache_size = total_size; + + ret = read_cache(&page); + if (ret < 0) + goto out; + + ret = fd_write_vmcore(page.buf, page.cache_size, s); + if (ret < 0) + goto out; + + total_size -= page.cache_size; + } + + /* switch to page_data */ + if (is_page_desc) { + is_page_desc = 0; + total_size = s->page_data_size; + page.fd = s->page_data->fd; + page.offset = s->page_data->offset; + goto again; + } + + return 0; + +out: + if (page.buf) + g_free(page.buf); + + return -1; +} + +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 + * | : | + * +------------------------------------------+ + */ + + 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; + } + + dump_completed(s); + + return 0; +} + static int create_header32(DumpState *s) { struct disk_dump_header32 *dh; diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h index b61c9ba..4913468 100644 --- a/include/sysemu/dump.h +++ b/include/sysemu/dump.h @@ -49,6 +49,7 @@ #define DISKDUMP_HEADER_BLOCKS (1) #define PHYS_BASE (0) #define DUMP_LEVEL (1) +#define TMP_BUF_SIZE (1024) #define ARCH_PFN_OFFSET (0) #define FILENAME_BITMAP1 "kdump_bitmap1_XXXXXX" #define FILENAME_BITMAP2 "kdump_bitmap2_XXXXXX" -- 1.7.1