Currently, 1st bitmap is created during cyclic process, but the
information represented by the 1st bitmap, originally present memory,
is still available from ELF program header table, so:

- we don't need to keep the 1st bitmap even in cyclic process, and

- it's possible to avoid the case where for incomplete crash dump
  generated in failure case due to for example ENOSPC, we don't know
  where memory is present.

Supported is a conversion from ELF to kdump-compressed format only,
not from ELF to ELF.

Signed-off-by: HATAYAMA Daisuke <[email protected]>
---
 makedumpfile.c |  240 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 216 insertions(+), 24 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 4b6c0ed..dafe83b 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -3052,10 +3052,23 @@ out:
                                MSG("The buffer size for the cyclic mode will 
");
                                MSG("be truncated to %lld byte.\n", 
free_memory);
                                /*
-                                * bufsize_cyclic is used to allocate 1st and 
2nd bitmap, 
-                                * so it should be truncated to the half of 
free_memory.
+                                * On conversion from ELF to ELF,
+                                * bufsize_cyclic is used to allocate
+                                * 1st and 2nd bitmap, so it should be
+                                * truncated to the half of
+                                * free_memory.
+                                *
+                                * On conversion from ELF to
+                                * kdump-compressed format, a whole
+                                * part of the 1st bitmap is created
+                                * first, so a whole part of
+                                * free_memory is used for the 2nd
+                                * bitmap.
                                 */
-                               info->bufsize_cyclic = free_memory / 2;
+                               if (info->flag_elf_dumpfile)
+                                       info->bufsize_cyclic = free_memory / 2;
+                               else
+                                       info->bufsize_cyclic = free_memory;
                        }
                }
 
@@ -3328,6 +3341,33 @@ clear_bit_on_2nd_bitmap_for_kernel(unsigned long long 
pfn)
        return clear_bit_on_2nd_bitmap(pfn);
 }
 
+int
+set_bit_on_2nd_bitmap(unsigned long long pfn)
+{
+       if (info->flag_cyclic) {
+               return set_bitmap_cyclic(info->partial_bitmap2, pfn, 1);
+       } else {
+               return set_bitmap(info->bitmap2, pfn, 1);
+       }
+}
+
+int
+set_bit_on_2nd_bitmap_for_kernel(unsigned long long pfn)
+{
+       unsigned long long maddr;
+
+       if (is_xen_memory()) {
+               maddr = ptom_xen(pfn_to_paddr(pfn));
+               if (maddr == NOT_PADDR) {
+                       ERRMSG("Can't convert a physical address(%llx) to 
machine address.\n",
+                           pfn_to_paddr(pfn));
+                       return FALSE;
+               }
+               pfn = paddr_to_pfn(maddr);
+       }
+       return set_bit_on_2nd_bitmap(pfn);
+}
+
 static inline int
 is_in_segs(unsigned long long paddr)
 {
@@ -4418,6 +4458,53 @@ exclude_zero_pages(void)
        return TRUE;
 }
 
+static int
+initialize_2nd_bitmap_cyclic(void)
+{
+       int i;
+       unsigned long long pfn;
+       unsigned long long phys_start, phys_end;
+       unsigned long long pfn_start, pfn_end;
+       unsigned long long pfn_start_roundup, pfn_end_round;
+       unsigned long pfn_start_byte, pfn_end_byte;
+
+       /*
+        * At first, clear all the bits on the 2nd-bitmap.
+        */
+       initialize_bitmap_cyclic(info->partial_bitmap2);
+
+       /*
+        * If page is on memory hole, set bit on the 2nd-bitmap.
+        */
+       for (i = 0; get_pt_load(i, &phys_start, &phys_end, NULL, NULL); i++) {
+               pfn_start = MAX(paddr_to_pfn(phys_start), 
info->cyclic_start_pfn);
+               pfn_end = MIN(paddr_to_pfn(phys_end), info->cyclic_end_pfn);
+
+               if (pfn_start >= pfn_end)
+                       continue;
+
+               pfn_start_roundup = roundup(pfn_start, BITPERBYTE);
+               pfn_end_round = round(pfn_end, BITPERBYTE);
+
+               for (pfn = pfn_start; pfn < pfn_start_roundup; ++pfn)
+                       if (!set_bit_on_2nd_bitmap_for_kernel(pfn))
+                               return FALSE;
+
+               pfn_start_byte = (pfn_start_roundup - info->cyclic_start_pfn) 
>> 3;
+               pfn_end_byte = (pfn_end_round - info->cyclic_start_pfn) >> 3;
+
+               memset(info->partial_bitmap2 + pfn_start_byte,
+                      0xff,
+                      pfn_end_byte - pfn_start_byte);
+
+               for (pfn = pfn_end_round; pfn < pfn_end; ++pfn)
+                       if (!set_bit_on_2nd_bitmap_for_kernel(pfn))
+                               return FALSE;
+       }
+
+       return TRUE;
+}
+
 int
 __exclude_unnecessary_pages(unsigned long mem_map,
     unsigned long long pfn_start, unsigned long long pfn_end)
@@ -4584,12 +4671,6 @@ exclude_unnecessary_pages(void)
        return TRUE;
 }
 
-void
-copy_bitmap_cyclic(void)
-{
-       memcpy(info->partial_bitmap2, info->partial_bitmap1, 
info->bufsize_cyclic);
-}
-
 int
 exclude_unnecessary_pages_cyclic(void)
 {
@@ -4597,10 +4678,8 @@ exclude_unnecessary_pages_cyclic(void)
        struct mem_map_data *mmd;
        struct timeval tv_start;
 
-       /*
-        * Copy 1st-bitmap to 2nd-bitmap.
-        */
-       copy_bitmap_cyclic();
+       if (!initialize_2nd_bitmap_cyclic())
+               return FALSE;
 
        if ((info->dump_level & DL_EXCLUDE_FREE) && !info->page_is_buddy)
                if (!exclude_free_page())
@@ -4657,7 +4736,7 @@ update_cyclic_region(unsigned long long pfn)
        if (info->cyclic_end_pfn > info->max_mapnr)
                info->cyclic_end_pfn = info->max_mapnr;
 
-       if (!create_1st_bitmap_cyclic())
+       if (info->flag_elf_dumpfile && !create_1st_bitmap_cyclic())
                return FALSE;
 
        if (!exclude_unnecessary_pages_cyclic())
@@ -4841,19 +4920,71 @@ prepare_bitmap_buffer_cyclic(void)
        return TRUE;
 }
 
+int
+prepare_bitmap1_buffer_cyclic(void)
+{
+       /*
+        * Prepare partial bitmap buffers for cyclic processing.
+        */
+       if ((info->partial_bitmap1 = (char *)malloc(info->bufsize_cyclic)) == 
NULL) {
+               ERRMSG("Can't allocate memory for the 1st bitmaps. %s\n",
+                      strerror(errno));
+               return FALSE;
+       }
+       initialize_bitmap_cyclic(info->partial_bitmap1);
+
+       return TRUE;
+}
+
+int
+prepare_bitmap2_buffer_cyclic(void)
+{
+       unsigned long tmp;
+
+       /*
+        * Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size
+        * boundary. The crash utility requires both of them to be
+        * aligned to block_size boundary.
+        */
+       tmp = divideup(divideup(info->max_mapnr, BITPERBYTE), info->page_size);
+       info->len_bitmap = tmp * info->page_size * 2;
+
+       /*
+        * Prepare partial bitmap buffers for cyclic processing.
+        */
+       if ((info->partial_bitmap2 = (char *)malloc(info->bufsize_cyclic)) == 
NULL) {
+               ERRMSG("Can't allocate memory for the 2nd bitmaps. %s\n",
+                      strerror(errno));
+               return FALSE;
+       }
+       initialize_bitmap_cyclic(info->partial_bitmap2);
+
+       return TRUE;
+}
+
 void
-free_bitmap_buffer(void)
+free_bitmap1_buffer(void)
 {
        if (info->bitmap1) {
                free(info->bitmap1);
                info->bitmap1 = NULL;
        }
+}
+
+void
+free_bitmap2_buffer(void)
+{
        if (info->bitmap2) {
                free(info->bitmap2);
                info->bitmap2 = NULL;
        }
+}
 
-       return;
+void
+free_bitmap_buffer(void)
+{
+       free_bitmap1_buffer();
+       free_bitmap2_buffer();
 }
 
 int
@@ -4862,10 +4993,21 @@ create_dump_bitmap(void)
        int ret = FALSE;
 
        if (info->flag_cyclic) {
-               if (!prepare_bitmap_buffer_cyclic())
-                       goto out;
 
-               info->num_dumpable = get_num_dumpable_cyclic();
+               if (info->flag_elf_dumpfile) {
+                       if (!prepare_bitmap_buffer_cyclic())
+                               goto out;
+
+                       info->num_dumpable = get_num_dumpable_cyclic();
+               } else {
+                       if (!prepare_bitmap2_buffer_cyclic())
+                               goto out;
+
+                       info->num_dumpable = get_num_dumpable_cyclic();
+
+                       free_bitmap2_buffer();
+               }
+
        } else {
                if (!prepare_bitmap_buffer())
                        goto out;
@@ -6564,7 +6706,7 @@ out:
 }
 
 int
-write_kdump_bitmap_cyclic(void)
+write_kdump_bitmap1_cyclic(void)
 {
        off_t offset;
         int increment;
@@ -6576,10 +6718,30 @@ write_kdump_bitmap_cyclic(void)
                return FALSE;
 
        offset = info->offset_bitmap1;
-       if (!write_buffer(info->fd_dumpfile, offset,
+       if (!write_buffer(info->fd_dumpfile, offset + info->bufsize_cyclic *
+                         (info->cyclic_start_pfn / info->pfn_cyclic),
                          info->partial_bitmap1, increment, 
info->name_dumpfile))
                goto out;
 
+       ret = TRUE;
+out:
+       return ret;
+}
+
+int
+write_kdump_bitmap2_cyclic(void)
+{
+       off_t offset;
+       int increment;
+       int ret = FALSE;
+
+       increment = divideup(info->cyclic_end_pfn - info->cyclic_start_pfn,
+                            BITPERBYTE);
+
+       if (info->flag_elf_dumpfile)
+               return FALSE;
+
+       offset = info->offset_bitmap1;
        offset += info->len_bitmap / 2;
        if (!write_buffer(info->fd_dumpfile, offset,
                          info->partial_bitmap2, increment, 
info->name_dumpfile))
@@ -6633,6 +6795,30 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data 
*cd_header, struct cache_d
        }
 
        /*
+        * Write the 1st bitmap
+        */
+       if (!prepare_bitmap1_buffer_cyclic())
+               return FALSE;
+
+       info->cyclic_start_pfn = 0;
+       info->cyclic_end_pfn = 0;
+       for (pfn = 0; pfn < info->max_mapnr; pfn++) {
+               if (is_cyclic_region(pfn))
+                       continue;
+               if (!update_cyclic_region(pfn))
+                       return FALSE;
+               if (!create_1st_bitmap_cyclic())
+                       return FALSE;
+               if (!write_kdump_bitmap1_cyclic())
+                       return FALSE;
+       }
+
+       free_bitmap1_buffer();
+
+       if (!prepare_bitmap2_buffer_cyclic())
+               return FALSE;
+
+       /*
         * Write pages and bitmap cyclically.
         */
        info->cyclic_start_pfn = 0;
@@ -6647,7 +6833,7 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data 
*cd_header, struct cache_d
                if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero, 
&offset_data))
                        return FALSE;
 
-               if (!write_kdump_bitmap_cyclic())
+               if (!write_kdump_bitmap2_cyclic())
                        return FALSE;
         }
 
@@ -8681,8 +8867,14 @@ calculate_cyclic_buffer_size(void) {
         * should be 40% of free memory to keep the size of cyclic buffer
         * within 80% of free memory.
         */
-       free_size = get_free_memory_size() * 0.4;
-       needed_size = (info->max_mapnr * 2) / BITPERBYTE;
+       if (info->flag_elf_dumpfile) {
+               free_size = get_free_memory_size() * 0.4;
+               needed_size = (info->max_mapnr * 2) / BITPERBYTE;
+       } else {
+               free_size = get_free_memory_size() * 0.8;
+               needed_size = info->max_mapnr / BITPERBYTE;
+       }
+
        /* if --split was specified cyclic buffer allocated per dump file */
        if (info->num_dumpfile > 1)
                needed_size /= info->num_dumpfile;


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to