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

2013-07-15 Thread Stefan Hajnoczi
On Tue, Jul 09, 2013 at 03:30:11PM +0800, Qiao Nuohan wrote:
 +/* 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;
 +}

Can you reuse sync_dump_bitmap() here instead of duplicating this code?



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

2013-07-09 Thread Qiao Nuohan
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 qiaonuo...@cn.fujitsu.com
Reviewed-by: Zhang Xiaohe zhan...@cn.fujitsu.com
---
 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] |= 1bit;
+} else {
+((char *)buf)[byte] = ~(1bit);
+}
+
+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:
+