[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 8/9 v3] Add API to write header, bitmap and page int
From: |
Qiao Nuohan |
Subject: |
[Qemu-devel] [PATCH 8/9 v3] Add API to write header, bitmap and page into vmcore |
Date: |
Fri, 17 May 2013 11:25:03 +0800 |
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 <address@hidden>
Reviewed-by: Zhang Xiaohe <address@hidden>
---
dump.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++++
include/sysemu/dump.h | 1 +
2 files changed, 260 insertions(+), 0 deletions(-)
diff --git a/dump.c b/dump.c
index 75ef032..c04e2ae 100644
--- a/dump.c
+++ b/dump.c
@@ -67,6 +67,36 @@ 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;
@@ -672,6 +702,235 @@ 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 27ee3fa..49e3621 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -48,6 +48,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
- [Qemu-devel] [PATCH 0/9 v3] Make monitor command 'dump-guest-memory' dump in kdump-compressed format, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 3/9 v3] Move includes and struct definition to dump.h, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 5/9 v3] Add API to create data of dump bitmap, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 1/9 v3] Add API to manipulate dump_bitmap, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 7/9 v3] Add API to free memory used by creating header, bitmap and page, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 2/9 v3] Add API to manipulate cache_data, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 4/9 v3] Add API to create header of vmcore, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 6/9 v3] Add API to create page, Qiao Nuohan, 2013/05/16
- [Qemu-devel] [PATCH 8/9 v3] Add API to write header, bitmap and page into vmcore,
Qiao Nuohan <=
- [Qemu-devel] [PATCH 9/9 v3] Make monitor command 'dump-guest-memory' dump in kdump-compressed format, Qiao Nuohan, 2013/05/16
- Re: [Qemu-devel] [PATCH 0/9 v3] Make monitor command 'dump-guest-memory' dump in kdump-compressed format, Qiao Nuohan, 2013/05/19
- Re: [Qemu-devel] [PATCH 0/9 v3] Make monitor command 'dump-guest-memory' dump in kdump-compressed format, Qiao Nuohan, 2013/05/22
- Re: [Qemu-devel] [PATCH 0/9 v3] Make monitor command 'dump-guest-memory' dump in kdump-compressed format, Andreas Färber, 2013/05/22