qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap


From: Qiao Nuohan
Subject: [Qemu-devel] [PATCH v5 6/9] dump: Add API to write dump_bitmap
Date: Tue, 9 Jul 2013 15:30:11 +0800

functions are used to write 1st and 2nd dump_bitmap of kdump-compressed format,
which is used to indicate whether the corresponded page is existed in vmcore.
Dump level 1 is chosen, so 1st and 2nd dump_bitmap are same.

Signed-off-by: Qiao Nuohan <address@hidden>
Reviewed-by: Zhang Xiaohe <address@hidden>
---
 dump.c                |  136 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/dump.h |    5 ++
 2 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/dump.c b/dump.c
index cb2f866..40a5ea5 100644
--- a/dump.c
+++ b/dump.c
@@ -79,12 +79,14 @@ typedef struct DumpState {
     bool flag_flatten;
     uint32_t nr_cpus;
     size_t page_size;
+    uint32_t page_shift;
     size_t max_mapnr;
     size_t len_dump_bitmap;
     void *note_buf;
     size_t note_buf_offset;
     off_t offset_dump_bitmap;
     off_t offset_page;
+    size_t num_dumpable;
 } DumpState;
 
 static int dump_cleanup(DumpState *s)
@@ -925,6 +927,140 @@ static int write_dump_header(DumpState *s)
     }
 }
 
+/* set dump_bitmap sequencely */
+static int set_dump_bitmap(int64_t last_pfn, int64_t pfn, uint32_t value,
+                           void *buf, DumpState *s)
+{
+    off_t old_offset, new_offset;
+    off_t offset_bitmap1, offset_bitmap2;
+    uint32_t byte, bit;
+
+    /* should not set the previous place */
+    if (last_pfn > pfn) {
+        return -1;
+    }
+
+    /*
+     * if the block needed to be set is not same as the one cached in buf, 
flush
+     * the cached buf to vmcore firstly
+     */
+    old_offset = BUFSIZE_BITMAP * (last_pfn / PFN_BUFBITMAP);
+    new_offset = BUFSIZE_BITMAP * (pfn / PFN_BUFBITMAP);
+
+    while (old_offset < new_offset) {
+        /* calculate the offset and write dump_bitmap */
+        offset_bitmap1 = s->offset_dump_bitmap + old_offset;
+        if (write_buffer(s->fd, s->flag_flatten, offset_bitmap1, buf,
+                         BUFSIZE_BITMAP) < 0) {
+            return -1;
+        }
+
+        /* dump level 1 is chosen, so 1st and 2nd bitmap are same */
+        offset_bitmap2 = s->offset_dump_bitmap + s->len_dump_bitmap / 2 +
+                         old_offset;
+        if (write_buffer(s->fd, s->flag_flatten, offset_bitmap2, buf,
+                         BUFSIZE_BITMAP) < 0) {
+            return -1;
+        }
+
+        memset(buf, 0, BUFSIZE_BITMAP);
+        old_offset += BUFSIZE_BITMAP;
+    }
+
+    /* get the exact place of the bit in the buf, and set it */
+    byte = (pfn % PFN_BUFBITMAP) >> 3;
+    bit = (pfn % PFN_BUFBITMAP) & 7;
+    if (value) {
+        ((char *)buf)[byte] |= 1<<bit;
+    } else {
+        ((char *)buf)[byte] &= ~(1<<bit);
+    }
+
+    return 0;
+}
+
+/* write the remaining dump_bitmap in buf to s->fd */
+static int sync_dump_bitmap(int64_t last_pfn, void *buf, DumpState *s)
+{
+    off_t last_offset, offset_bitmap1, offset_bitmap2;
+
+    /* nothing is stored in buf */
+    if (last_pfn < 0) {
+        return 0;
+    }
+
+    last_offset = BUFSIZE_BITMAP * (last_pfn / PFN_BUFBITMAP);
+
+    /* calculate the offset and write dump_bitmap */
+    offset_bitmap1 = s->offset_dump_bitmap + last_offset;
+    if (write_buffer(s->fd, s->flag_flatten, offset_bitmap1, buf,
+                     BUFSIZE_BITMAP) < 0) {
+        return -1;
+    }
+
+    offset_bitmap2 = s->offset_dump_bitmap + s->len_dump_bitmap / 2 +
+                     last_offset;
+    if (write_buffer(s->fd, s->flag_flatten, offset_bitmap2, buf,
+                     BUFSIZE_BITMAP) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_dump_bitmap(DumpState *s)
+{
+    int ret = 0;
+    int64_t pfn_start, pfn_end, pfn;
+    int64_t last_pfn;
+    void *dump_bitmap_buf;
+    size_t num_dumpable;
+    MemoryMapping *memory_mapping;
+
+    /* dump_bitmap_buf is used to store dump_bitmap temporarily */
+    dump_bitmap_buf = g_malloc0(BUFSIZE_BITMAP);
+
+    num_dumpable = 0;
+    last_pfn = -1;
+
+    /*
+     * exam memory page by page, and set the bit in dump_bitmap corresponded
+     * to the existing page
+     */
+    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+        pfn_start = paddr_to_pfn(memory_mapping->phys_addr, s->page_shift);
+        pfn_end = paddr_to_pfn(memory_mapping->phys_addr +
+                               memory_mapping->length, s->page_shift);
+
+        for (pfn = pfn_start; pfn < pfn_end; pfn++) {
+            ret = set_dump_bitmap(last_pfn, pfn, 1, dump_bitmap_buf, s);
+            if (ret < 0) {
+                dump_error(s, "dump: failed to set dump_bitmap.\n");
+                ret = -1;
+                goto out;
+            }
+
+            last_pfn = pfn;
+            num_dumpable++;
+        }
+    }
+
+    ret = sync_dump_bitmap(last_pfn, dump_bitmap_buf, s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to sync dump_bitmap.\n");
+        ret = -1;
+        goto out;
+    }
+
+    /* number of dumpable pages that will be dumped later */
+    s->num_dumpable = num_dumpable;
+
+out:
+    g_free(dump_bitmap_buf);
+
+    return ret;
+}
+
 static ram_addr_t get_start_block(DumpState *s)
 {
     RAMBlock *block;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 54ae4e5..e67927d 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -25,8 +25,13 @@
 #define PHYS_BASE                   (0)
 #define DUMP_LEVEL                  (1)
 #define DISKDUMP_HEADER_BLOCKS      (1)
+#define BUFSIZE_BITMAP              (4096)
+#define PFN_BUFBITMAP               (CHAR_BIT * BUFSIZE_BITMAP)
+#define ARCH_PFN_OFFSET             (0)
 
 #define divideup(x, y)              (((x) + ((y) - 1)) / (y))
+#define paddr_to_pfn(X, page_shift) \
+    (((unsigned long long)(X) >> (page_shift)) - ARCH_PFN_OFFSET)
 
 typedef struct ArchDumpInfo {
     int d_machine;  /* Architecture */
-- 
1.7.1




reply via email to

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